mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
applying uncrustify to ensure uniform indentation
This commit is contained in:
@@ -48,3 +48,4 @@ po/configargs.stamp
|
||||
**~
|
||||
doc/libmicrohttpd.log
|
||||
src/examples/suspend_resume_epoll
|
||||
uncrustify.cfg
|
||||
|
||||
@@ -8,4 +8,27 @@ fi
|
||||
|
||||
test -n "$bs_scrdir" && cd "$bs_scrdir" || echo "Warning: cannot get sources directory" 1>&2
|
||||
|
||||
autoreconf -I m4 -i ${1+"$@"}
|
||||
# This is more portable than `which' but comes with
|
||||
# the caveat of not(?) properly working on busybox's ash:
|
||||
existence()
|
||||
{
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
|
||||
if existence uncrustify; then
|
||||
echo "Installing uncrustify hook and configuration"
|
||||
# Install uncrustify format symlink (if possible)
|
||||
ln -s contrib/uncrustify.cfg uncrustify.cfg 2> /dev/null
|
||||
# Install pre-commit hook (if possible)
|
||||
ln -s ../../contrib/uncrustify_precommit .git/hooks/pre-commit 2> /dev/null
|
||||
else
|
||||
echo "Uncrustify not detected, hook not installed. Please install uncrustify if you plan on doing development"
|
||||
fi
|
||||
|
||||
if existence libtool || existence libtoolize || existence glibtoolize || existence slibtool; then
|
||||
autoreconf -I m4 -i ${1+"$@"}
|
||||
else
|
||||
echo "*** No libtoolize (libtool) or libtool found, please install it ***" >&2;
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -4,7 +4,7 @@ output_tab_size = 2
|
||||
indent_columns = 2
|
||||
indent_with_tabs = 0
|
||||
indent_case_brace = 2
|
||||
indent_label=0
|
||||
indent_label=-16
|
||||
|
||||
code_width=80
|
||||
#cmd_width=80
|
||||
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
|
||||
# use as .git/hooks/pre-commit
|
||||
|
||||
exec 1>&2
|
||||
|
||||
RET=0
|
||||
changed=$(git diff --cached --name-only)
|
||||
crustified=""
|
||||
|
||||
for f in $changed;
|
||||
do
|
||||
if echo $f | grep \\.[c,h]\$ > /dev/null
|
||||
then
|
||||
# compare result of uncrustify with changes
|
||||
#
|
||||
# only change any of the invocations here if
|
||||
# they are portable across all cmp and shell
|
||||
# implementations !
|
||||
uncrustify -q -c uncrustify.cfg -f $f | cmp -s $f -
|
||||
if test $? = 1 ;
|
||||
then
|
||||
crustified=" $crustified $f"
|
||||
RET=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $RET = 1 ];
|
||||
then
|
||||
echo "Run"
|
||||
echo "uncrustify --no-backup -c uncrustify.cfg ${crustified}"
|
||||
echo "before commiting."
|
||||
fi
|
||||
exit $RET
|
||||
@@ -32,9 +32,11 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
|
||||
#define PAGE \
|
||||
"<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
|
||||
|
||||
#define DENIED "<html><head><title>Access denied</title></head><body>Access denied</body></html>"
|
||||
#define DENIED \
|
||||
"<html><head><title>Access denied</title></head><body>Access denied</body></html>"
|
||||
|
||||
|
||||
|
||||
@@ -53,19 +55,19 @@ ahc_echo (void *cls,
|
||||
char *user;
|
||||
char *pass;
|
||||
int fail;
|
||||
(void)url; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) url; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 != strcmp (method, "GET"))
|
||||
return MHD_NO; /* unexpected method */
|
||||
if (&aptr != *ptr)
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
*ptr = NULL; /* reset when done */
|
||||
|
||||
/* require: "Aladdin" with password "open sesame" */
|
||||
@@ -77,18 +79,18 @@ ahc_echo (void *cls,
|
||||
(0 != strcmp (pass, "open sesame") ) );
|
||||
if (fail)
|
||||
{
|
||||
response = MHD_create_response_from_buffer (strlen (DENIED),
|
||||
(void *) DENIED,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_basic_auth_fail_response (connection,"TestRealm",response);
|
||||
}
|
||||
response = MHD_create_response_from_buffer (strlen (DENIED),
|
||||
(void *) DENIED,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_basic_auth_fail_response (connection,"TestRealm",response);
|
||||
}
|
||||
else
|
||||
{
|
||||
response = MHD_create_response_from_buffer (strlen (me),
|
||||
(void *) me,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
}
|
||||
{
|
||||
response = MHD_create_response_from_buffer (strlen (me),
|
||||
(void *) me,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
}
|
||||
if (NULL != user)
|
||||
MHD_free (user);
|
||||
if (NULL != pass)
|
||||
@@ -107,13 +109,14 @@ main (int argc, char *const *argv)
|
||||
if ( (argc != 2) ||
|
||||
(1 != sscanf (argv[1], "%u", &port)) ||
|
||||
(UINT16_MAX < port) )
|
||||
{
|
||||
fprintf (stderr,
|
||||
"%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
fprintf (stderr,
|
||||
"%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION
|
||||
| MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
atoi (argv[1]),
|
||||
NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
|
||||
if (d == NULL)
|
||||
|
||||
+41
-38
@@ -25,14 +25,15 @@
|
||||
#include "platform.h"
|
||||
#include <microhttpd.h>
|
||||
|
||||
#if defined(CPU_COUNT) && (CPU_COUNT+0) < 2
|
||||
#if defined(CPU_COUNT) && (CPU_COUNT + 0) < 2
|
||||
#undef CPU_COUNT
|
||||
#endif
|
||||
#if !defined(CPU_COUNT)
|
||||
#if ! defined(CPU_COUNT)
|
||||
#define CPU_COUNT 2
|
||||
#endif
|
||||
|
||||
#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
|
||||
#define PAGE \
|
||||
"<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
|
||||
|
||||
|
||||
#define SMALL (1024 * 128)
|
||||
@@ -62,16 +63,16 @@ static struct MHD_Response *response;
|
||||
*/
|
||||
static void
|
||||
completed_callback (void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
void **con_cls,
|
||||
enum MHD_RequestTerminationCode toe)
|
||||
struct MHD_Connection *connection,
|
||||
void **con_cls,
|
||||
enum MHD_RequestTerminationCode toe)
|
||||
{
|
||||
struct timeval *tv = *con_cls;
|
||||
struct timeval tve;
|
||||
uint64_t delta;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)connection; /* Unused. Silent compiler warning. */
|
||||
(void)toe; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) connection; /* Unused. Silent compiler warning. */
|
||||
(void) toe; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (NULL == tv)
|
||||
return;
|
||||
@@ -80,10 +81,10 @@ completed_callback (void *cls,
|
||||
delta = 0;
|
||||
if (tve.tv_usec >= tv->tv_usec)
|
||||
delta += (tve.tv_sec - tv->tv_sec) * 1000000LL
|
||||
+ (tve.tv_usec - tv->tv_usec);
|
||||
+ (tve.tv_usec - tv->tv_usec);
|
||||
else
|
||||
delta += (tve.tv_sec - tv->tv_sec) * 1000000LL
|
||||
- tv->tv_usec + tve.tv_usec;
|
||||
- tv->tv_usec + tve.tv_usec;
|
||||
if (delta < SMALL)
|
||||
small_deltas[delta]++;
|
||||
else
|
||||
@@ -94,11 +95,11 @@ completed_callback (void *cls,
|
||||
|
||||
static void *
|
||||
uri_logger_cb (void *cls,
|
||||
const char *uri)
|
||||
const char *uri)
|
||||
{
|
||||
struct timeval *tv = malloc (sizeof (struct timeval));
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)uri; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) uri; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (NULL != tv)
|
||||
gettimeofday (tv, NULL);
|
||||
@@ -114,12 +115,12 @@ ahc_echo (void *cls,
|
||||
const char *version,
|
||||
const char *upload_data, size_t *upload_data_size, void **ptr)
|
||||
{
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)url; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void)ptr; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) url; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) ptr; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 != strcmp (method, "GET"))
|
||||
return MHD_NO; /* unexpected method */
|
||||
@@ -134,37 +135,39 @@ main (int argc, char *const *argv)
|
||||
unsigned int i;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
response = MHD_create_response_from_buffer (strlen (PAGE),
|
||||
(void *) PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
(void *) PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
#if 0
|
||||
(void) MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"close");
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"close");
|
||||
#endif
|
||||
d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_SUPPRESS_DATE_NO_CLOCK
|
||||
d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD
|
||||
| MHD_USE_SUPPRESS_DATE_NO_CLOCK
|
||||
#ifdef EPOLL_SUPPORT
|
||||
| MHD_USE_EPOLL | MHD_USE_TURBO
|
||||
| MHD_USE_EPOLL | MHD_USE_TURBO
|
||||
#endif
|
||||
,
|
||||
,
|
||||
atoi (argv[1]),
|
||||
NULL, NULL, &ahc_echo, NULL,
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120,
|
||||
MHD_OPTION_THREAD_POOL_SIZE, (unsigned int) NUMBER_OF_THREADS,
|
||||
MHD_OPTION_URI_LOG_CALLBACK, &uri_logger_cb, NULL,
|
||||
MHD_OPTION_NOTIFY_COMPLETED, &completed_callback, NULL,
|
||||
MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 1000,
|
||||
MHD_OPTION_END);
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120,
|
||||
MHD_OPTION_THREAD_POOL_SIZE, (unsigned
|
||||
int) NUMBER_OF_THREADS,
|
||||
MHD_OPTION_URI_LOG_CALLBACK, &uri_logger_cb, NULL,
|
||||
MHD_OPTION_NOTIFY_COMPLETED, &completed_callback, NULL,
|
||||
MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 1000,
|
||||
MHD_OPTION_END);
|
||||
if (d == NULL)
|
||||
return 1;
|
||||
(void) getc (stdin);
|
||||
MHD_stop_daemon (d);
|
||||
MHD_destroy_response (response);
|
||||
for (i=0;i<SMALL;i++)
|
||||
for (i = 0; i<SMALL; i++)
|
||||
if (0 != small_deltas[i])
|
||||
fprintf (stdout, "D: %d %u\n", i, small_deltas[i]);
|
||||
return 0;
|
||||
|
||||
@@ -25,14 +25,15 @@
|
||||
#include "platform.h"
|
||||
#include <microhttpd.h>
|
||||
|
||||
#if defined(CPU_COUNT) && (CPU_COUNT+0) < 2
|
||||
#if defined(CPU_COUNT) && (CPU_COUNT + 0) < 2
|
||||
#undef CPU_COUNT
|
||||
#endif
|
||||
#if !defined(CPU_COUNT)
|
||||
#if ! defined(CPU_COUNT)
|
||||
#define CPU_COUNT 2
|
||||
#endif
|
||||
|
||||
#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
|
||||
#define PAGE \
|
||||
"<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
|
||||
|
||||
|
||||
#define SMALL (1024 * 128)
|
||||
@@ -62,16 +63,16 @@ static struct MHD_Response *response;
|
||||
*/
|
||||
static void
|
||||
completed_callback (void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
void **con_cls,
|
||||
enum MHD_RequestTerminationCode toe)
|
||||
struct MHD_Connection *connection,
|
||||
void **con_cls,
|
||||
enum MHD_RequestTerminationCode toe)
|
||||
{
|
||||
struct timeval *tv = *con_cls;
|
||||
struct timeval tve;
|
||||
uint64_t delta;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)connection; /* Unused. Silent compiler warning. */
|
||||
(void)toe; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) connection; /* Unused. Silent compiler warning. */
|
||||
(void) toe; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (NULL == tv)
|
||||
return;
|
||||
@@ -80,10 +81,10 @@ completed_callback (void *cls,
|
||||
delta = 0;
|
||||
if (tve.tv_usec >= tv->tv_usec)
|
||||
delta += (tve.tv_sec - tv->tv_sec) * 1000000LL
|
||||
+ (tve.tv_usec - tv->tv_usec);
|
||||
+ (tve.tv_usec - tv->tv_usec);
|
||||
else
|
||||
delta += (tve.tv_sec - tv->tv_sec) * 1000000LL
|
||||
- tv->tv_usec + tve.tv_usec;
|
||||
- tv->tv_usec + tve.tv_usec;
|
||||
if (delta < SMALL)
|
||||
small_deltas[delta]++;
|
||||
else
|
||||
@@ -94,11 +95,11 @@ completed_callback (void *cls,
|
||||
|
||||
static void *
|
||||
uri_logger_cb (void *cls,
|
||||
const char *uri)
|
||||
const char *uri)
|
||||
{
|
||||
struct timeval *tv = malloc (sizeof (struct timeval));
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)uri; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) uri; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (NULL != tv)
|
||||
gettimeofday (tv, NULL);
|
||||
@@ -114,12 +115,12 @@ ahc_echo (void *cls,
|
||||
const char *version,
|
||||
const char *upload_data, size_t *upload_data_size, void **ptr)
|
||||
{
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)url; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void)ptr; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) url; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) ptr; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 != strcmp (method, "GET"))
|
||||
return MHD_NO; /* unexpected method */
|
||||
@@ -129,53 +130,53 @@ ahc_echo (void *cls,
|
||||
|
||||
/* test server key */
|
||||
const char srv_signed_key_pem[] = "-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
"MIIEowIBAAKCAQEAvfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW\n"
|
||||
"+K03KwEku55QvnUndwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8IL\n"
|
||||
"q4sw32vo0fbMu5BZF49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ0\n"
|
||||
"20Q5EAAEseD1YtWCIpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6\n"
|
||||
"QYGGh1QmHRPAy3CBII6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6x\n"
|
||||
"yoOl204xuekZOaG9RUPId74Rtmwfi1TLbBzo2wIDAQABAoIBADu09WSICNq5cMe4\n"
|
||||
"+NKCLlgAT1NiQpLls1gKRbDhKiHU9j8QWNvWWkJWrCya4QdUfLCfeddCMeiQmv3K\n"
|
||||
"lJMvDs+5OjJSHFoOsGiuW2Ias7IjnIojaJalfBml6frhJ84G27IXmdz6gzOiTIer\n"
|
||||
"DjeAgcwBaKH5WwIay2TxIaScl7AwHBauQkrLcyb4hTmZuQh6ArVIN6+pzoVuORXM\n"
|
||||
"bpeNWl2l/HSN3VtUN6aCAKbN/X3o0GavCCMn5Fa85uJFsab4ss/uP+2PusU71+zP\n"
|
||||
"sBm6p/2IbGvF5k3VPDA7X5YX61sukRjRBihY8xSnNYx1UcoOsX6AiPnbhifD8+xQ\n"
|
||||
"Tlf8oJUCgYEA0BTfzqNpr9Wxw5/QXaSdw7S/0eP5a0C/nwURvmfSzuTD4equzbEN\n"
|
||||
"d+dI/s2JMxrdj/I4uoAfUXRGaabevQIjFzC9uyE3LaOyR2zhuvAzX+vVcs6bSXeU\n"
|
||||
"pKpCAcN+3Z3evMaX2f+z/nfSUAl2i4J2R+/LQAWJW4KwRky/m+cxpfUCgYEA6bN1\n"
|
||||
"b73bMgM8wpNt6+fcmS+5n0iZihygQ2U2DEud8nZJL4Nrm1dwTnfZfJBnkGj6+0Q0\n"
|
||||
"cOwj2KS0/wcEdJBP0jucU4v60VMhp75AQeHqidIde0bTViSRo3HWKXHBIFGYoU3T\n"
|
||||
"LyPyKndbqsOObnsFXHn56Nwhr2HLf6nw4taGQY8CgYBoSW36FLCNbd6QGvLFXBGt\n"
|
||||
"2lMhEM8az/K58kJ4WXSwOLtr6MD/WjNT2tkcy0puEJLm6BFCd6A6pLn9jaKou/92\n"
|
||||
"SfltZjJPb3GUlp9zn5tAAeSSi7YMViBrfuFiHObij5LorefBXISLjuYbMwL03MgH\n"
|
||||
"Ocl2JtA2ywMp2KFXs8GQWQKBgFyIVv5ogQrbZ0pvj31xr9HjqK6d01VxIi+tOmpB\n"
|
||||
"4ocnOLEcaxX12BzprW55ytfOCVpF1jHD/imAhb3YrHXu0fwe6DXYXfZV4SSG2vB7\n"
|
||||
"IB9z14KBN5qLHjNGFpMQXHSMek+b/ftTU0ZnPh9uEM5D3YqRLVd7GcdUhHvG8P8Q\n"
|
||||
"C9aXAoGBAJtID6h8wOGMP0XYX5YYnhlC7dOLfk8UYrzlp3xhqVkzKthTQTj6wx9R\n"
|
||||
"GtC4k7U1ki8oJsfcIlBNXd768fqDVWjYju5rzShMpo8OCTS6ipAblKjCxPPVhIpv\n"
|
||||
"tWPlbSn1qj6wylstJ5/3Z+ZW5H4wIKp5jmLiioDhcP0L/Ex3Zx8O\n"
|
||||
"-----END RSA PRIVATE KEY-----\n";
|
||||
"MIIEowIBAAKCAQEAvfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW\n"
|
||||
"+K03KwEku55QvnUndwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8IL\n"
|
||||
"q4sw32vo0fbMu5BZF49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ0\n"
|
||||
"20Q5EAAEseD1YtWCIpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6\n"
|
||||
"QYGGh1QmHRPAy3CBII6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6x\n"
|
||||
"yoOl204xuekZOaG9RUPId74Rtmwfi1TLbBzo2wIDAQABAoIBADu09WSICNq5cMe4\n"
|
||||
"+NKCLlgAT1NiQpLls1gKRbDhKiHU9j8QWNvWWkJWrCya4QdUfLCfeddCMeiQmv3K\n"
|
||||
"lJMvDs+5OjJSHFoOsGiuW2Ias7IjnIojaJalfBml6frhJ84G27IXmdz6gzOiTIer\n"
|
||||
"DjeAgcwBaKH5WwIay2TxIaScl7AwHBauQkrLcyb4hTmZuQh6ArVIN6+pzoVuORXM\n"
|
||||
"bpeNWl2l/HSN3VtUN6aCAKbN/X3o0GavCCMn5Fa85uJFsab4ss/uP+2PusU71+zP\n"
|
||||
"sBm6p/2IbGvF5k3VPDA7X5YX61sukRjRBihY8xSnNYx1UcoOsX6AiPnbhifD8+xQ\n"
|
||||
"Tlf8oJUCgYEA0BTfzqNpr9Wxw5/QXaSdw7S/0eP5a0C/nwURvmfSzuTD4equzbEN\n"
|
||||
"d+dI/s2JMxrdj/I4uoAfUXRGaabevQIjFzC9uyE3LaOyR2zhuvAzX+vVcs6bSXeU\n"
|
||||
"pKpCAcN+3Z3evMaX2f+z/nfSUAl2i4J2R+/LQAWJW4KwRky/m+cxpfUCgYEA6bN1\n"
|
||||
"b73bMgM8wpNt6+fcmS+5n0iZihygQ2U2DEud8nZJL4Nrm1dwTnfZfJBnkGj6+0Q0\n"
|
||||
"cOwj2KS0/wcEdJBP0jucU4v60VMhp75AQeHqidIde0bTViSRo3HWKXHBIFGYoU3T\n"
|
||||
"LyPyKndbqsOObnsFXHn56Nwhr2HLf6nw4taGQY8CgYBoSW36FLCNbd6QGvLFXBGt\n"
|
||||
"2lMhEM8az/K58kJ4WXSwOLtr6MD/WjNT2tkcy0puEJLm6BFCd6A6pLn9jaKou/92\n"
|
||||
"SfltZjJPb3GUlp9zn5tAAeSSi7YMViBrfuFiHObij5LorefBXISLjuYbMwL03MgH\n"
|
||||
"Ocl2JtA2ywMp2KFXs8GQWQKBgFyIVv5ogQrbZ0pvj31xr9HjqK6d01VxIi+tOmpB\n"
|
||||
"4ocnOLEcaxX12BzprW55ytfOCVpF1jHD/imAhb3YrHXu0fwe6DXYXfZV4SSG2vB7\n"
|
||||
"IB9z14KBN5qLHjNGFpMQXHSMek+b/ftTU0ZnPh9uEM5D3YqRLVd7GcdUhHvG8P8Q\n"
|
||||
"C9aXAoGBAJtID6h8wOGMP0XYX5YYnhlC7dOLfk8UYrzlp3xhqVkzKthTQTj6wx9R\n"
|
||||
"GtC4k7U1ki8oJsfcIlBNXd768fqDVWjYju5rzShMpo8OCTS6ipAblKjCxPPVhIpv\n"
|
||||
"tWPlbSn1qj6wylstJ5/3Z+ZW5H4wIKp5jmLiioDhcP0L/Ex3Zx8O\n"
|
||||
"-----END RSA PRIVATE KEY-----\n";
|
||||
|
||||
/* test server CA signed certificates */
|
||||
const char srv_signed_cert_pem[] = "-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDGzCCAgWgAwIBAgIES0KCvTALBgkqhkiG9w0BAQUwFzEVMBMGA1UEAxMMdGVz\n"
|
||||
"dF9jYV9jZXJ0MB4XDTEwMDEwNTAwMDcyNVoXDTQ1MDMxMjAwMDcyNVowFzEVMBMG\n"
|
||||
"A1UEAxMMdGVzdF9jYV9jZXJ0MIIBHzALBgkqhkiG9w0BAQEDggEOADCCAQkCggEA\n"
|
||||
"vfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW+K03KwEku55QvnUn\n"
|
||||
"dwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8ILq4sw32vo0fbMu5BZ\n"
|
||||
"F49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ020Q5EAAEseD1YtWC\n"
|
||||
"IpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6QYGGh1QmHRPAy3CB\n"
|
||||
"II6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6xyoOl204xuekZOaG9\n"
|
||||
"RUPId74Rtmwfi1TLbBzo2wIDAQABo3YwdDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQM\n"
|
||||
"MAoGCCsGAQUFBwMBMA8GA1UdDwEB/wQFAwMHIAAwHQYDVR0OBBYEFOFi4ilKOP1d\n"
|
||||
"XHlWCMwmVKr7mgy8MB8GA1UdIwQYMBaAFP2olB4s2T/xuoQ5pT2RKojFwZo2MAsG\n"
|
||||
"CSqGSIb3DQEBBQOCAQEAHVWPxazupbOkG7Did+dY9z2z6RjTzYvurTtEKQgzM2Vz\n"
|
||||
"GQBA+3pZ3c5mS97fPIs9hZXfnQeelMeZ2XP1a+9vp35bJjZBBhVH+pqxjCgiUflg\n"
|
||||
"A3Zqy0XwwVCgQLE2HyaU3DLUD/aeIFK5gJaOSdNTXZLv43K8kl4cqDbMeRpVTbkt\n"
|
||||
"YmG4AyEOYRNKGTqMEJXJoxD5E3rBUNrVI/XyTjYrulxbNPcMWEHKNeeqWpKDYTFo\n"
|
||||
"Bb01PCthGXiq/4A2RLAFosadzRa8SBpoSjPPfZ0b2w4MJpReHqKbR5+T2t6hzml6\n"
|
||||
"4ToyOKPDmamiTuN5KzLN3cw7DQlvWMvqSOChPLnA3Q==\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
"MIIDGzCCAgWgAwIBAgIES0KCvTALBgkqhkiG9w0BAQUwFzEVMBMGA1UEAxMMdGVz\n"
|
||||
"dF9jYV9jZXJ0MB4XDTEwMDEwNTAwMDcyNVoXDTQ1MDMxMjAwMDcyNVowFzEVMBMG\n"
|
||||
"A1UEAxMMdGVzdF9jYV9jZXJ0MIIBHzALBgkqhkiG9w0BAQEDggEOADCCAQkCggEA\n"
|
||||
"vfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW+K03KwEku55QvnUn\n"
|
||||
"dwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8ILq4sw32vo0fbMu5BZ\n"
|
||||
"F49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ020Q5EAAEseD1YtWC\n"
|
||||
"IpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6QYGGh1QmHRPAy3CB\n"
|
||||
"II6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6xyoOl204xuekZOaG9\n"
|
||||
"RUPId74Rtmwfi1TLbBzo2wIDAQABo3YwdDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQM\n"
|
||||
"MAoGCCsGAQUFBwMBMA8GA1UdDwEB/wQFAwMHIAAwHQYDVR0OBBYEFOFi4ilKOP1d\n"
|
||||
"XHlWCMwmVKr7mgy8MB8GA1UdIwQYMBaAFP2olB4s2T/xuoQ5pT2RKojFwZo2MAsG\n"
|
||||
"CSqGSIb3DQEBBQOCAQEAHVWPxazupbOkG7Did+dY9z2z6RjTzYvurTtEKQgzM2Vz\n"
|
||||
"GQBA+3pZ3c5mS97fPIs9hZXfnQeelMeZ2XP1a+9vp35bJjZBBhVH+pqxjCgiUflg\n"
|
||||
"A3Zqy0XwwVCgQLE2HyaU3DLUD/aeIFK5gJaOSdNTXZLv43K8kl4cqDbMeRpVTbkt\n"
|
||||
"YmG4AyEOYRNKGTqMEJXJoxD5E3rBUNrVI/XyTjYrulxbNPcMWEHKNeeqWpKDYTFo\n"
|
||||
"Bb01PCthGXiq/4A2RLAFosadzRa8SBpoSjPPfZ0b2w4MJpReHqKbR5+T2t6hzml6\n"
|
||||
"4ToyOKPDmamiTuN5KzLN3cw7DQlvWMvqSOChPLnA3Q==\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
|
||||
int
|
||||
@@ -185,36 +186,37 @@ main (int argc, char *const *argv)
|
||||
unsigned int i;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
response = MHD_create_response_from_buffer (strlen (PAGE),
|
||||
(void *) PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
(void *) PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS
|
||||
#ifdef EPOLL_SUPPORT
|
||||
| MHD_USE_EPOLL | MHD_USE_TURBO
|
||||
| MHD_USE_EPOLL | MHD_USE_TURBO
|
||||
#endif
|
||||
,
|
||||
,
|
||||
atoi (argv[1]),
|
||||
NULL, NULL, &ahc_echo, NULL,
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120,
|
||||
MHD_OPTION_THREAD_POOL_SIZE, (unsigned int) NUMBER_OF_THREADS,
|
||||
MHD_OPTION_URI_LOG_CALLBACK, &uri_logger_cb, NULL,
|
||||
MHD_OPTION_NOTIFY_COMPLETED, &completed_callback, NULL,
|
||||
MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 1000,
|
||||
/* Optionally, the gnutls_load_file() can be used to
|
||||
load the key and the certificate from file. */
|
||||
MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem,
|
||||
MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem,
|
||||
MHD_OPTION_END);
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120,
|
||||
MHD_OPTION_THREAD_POOL_SIZE, (unsigned
|
||||
int) NUMBER_OF_THREADS,
|
||||
MHD_OPTION_URI_LOG_CALLBACK, &uri_logger_cb, NULL,
|
||||
MHD_OPTION_NOTIFY_COMPLETED, &completed_callback, NULL,
|
||||
MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 1000,
|
||||
/* Optionally, the gnutls_load_file() can be used to
|
||||
load the key and the certificate from file. */
|
||||
MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem,
|
||||
MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem,
|
||||
MHD_OPTION_END);
|
||||
if (d == NULL)
|
||||
return 1;
|
||||
(void) getc (stdin);
|
||||
MHD_stop_daemon (d);
|
||||
MHD_destroy_response (response);
|
||||
for (i=0;i<SMALL;i++)
|
||||
for (i = 0; i<SMALL; i++)
|
||||
if (0 != small_deltas[i])
|
||||
fprintf (stdout, "D: %d %u\n", i, small_deltas[i]);
|
||||
return 0;
|
||||
|
||||
@@ -40,15 +40,15 @@ callback (void *cls,
|
||||
size_t buf_size)
|
||||
{
|
||||
size_t size_to_copy;
|
||||
struct ResponseContentCallbackParam * const param =
|
||||
(struct ResponseContentCallbackParam *)cls;
|
||||
struct ResponseContentCallbackParam *const param =
|
||||
(struct ResponseContentCallbackParam *) cls;
|
||||
|
||||
/* Note: 'pos' will never exceed size of transmitted data. */
|
||||
/* You can use 'pos == param->response_size' in next check. */
|
||||
if (pos >= param->response_size)
|
||||
{ /* Whole response was sent. Signal end of response. */
|
||||
return MHD_CONTENT_READER_END_OF_STREAM;
|
||||
}
|
||||
{ /* Whole response was sent. Signal end of response. */
|
||||
return MHD_CONTENT_READER_END_OF_STREAM;
|
||||
}
|
||||
|
||||
/* Pseudo code. *
|
||||
if (data_not_ready)
|
||||
@@ -82,12 +82,13 @@ callback (void *cls,
|
||||
static void
|
||||
free_callback_param (void *cls)
|
||||
{
|
||||
free(cls);
|
||||
free (cls);
|
||||
}
|
||||
|
||||
|
||||
static const char simple_response_text[] = "<html><head><title>Simple response</title></head>"
|
||||
"<body>Simple response text</body></html>";
|
||||
static const char simple_response_text[] =
|
||||
"<html><head><title>Simple response</title></head>"
|
||||
"<body>Simple response text</body></html>";
|
||||
|
||||
|
||||
static int
|
||||
@@ -104,27 +105,28 @@ ahc_echo (void *cls,
|
||||
struct ResponseContentCallbackParam *callback_param;
|
||||
struct MHD_Response *response;
|
||||
int ret;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)url; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) url; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 != strcmp (method, "GET"))
|
||||
return MHD_NO; /* unexpected method */
|
||||
if (&aptr != *ptr)
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
callback_param = malloc (sizeof(struct ResponseContentCallbackParam));
|
||||
if (NULL == callback_param)
|
||||
return MHD_NO; /* Not enough memory. */
|
||||
|
||||
callback_param->response_data = simple_response_text;
|
||||
callback_param->response_size = (sizeof(simple_response_text)/sizeof(char)) - 1;
|
||||
callback_param->response_size = (sizeof(simple_response_text)
|
||||
/ sizeof(char)) - 1;
|
||||
|
||||
*ptr = NULL; /* reset when done */
|
||||
response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
|
||||
@@ -150,28 +152,28 @@ main (int argc, char *const *argv)
|
||||
int port;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
port = atoi (argv[1]);
|
||||
if ( (1 > port) ||
|
||||
(port > UINT16_MAX) )
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Port must be a number between 1 and 65535\n");
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Port must be a number between 1 and 65535\n");
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (/* MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, */
|
||||
MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
/* MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_POLL, */
|
||||
/* MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_POLL, */
|
||||
/* MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, */
|
||||
(uint16_t) port,
|
||||
NULL, NULL,
|
||||
&ahc_echo, NULL,
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120,
|
||||
MHD_OPTION_END);
|
||||
MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
/* MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_POLL, */
|
||||
/* MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_POLL, */
|
||||
/* MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, */
|
||||
(uint16_t) port,
|
||||
NULL, NULL,
|
||||
&ahc_echo, NULL,
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120,
|
||||
MHD_OPTION_END);
|
||||
if (NULL == d)
|
||||
return 1;
|
||||
(void) getc (stdin);
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
#include "platform.h"
|
||||
#include <microhttpd.h>
|
||||
|
||||
#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
|
||||
#define PAGE \
|
||||
"<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
|
||||
|
||||
static int
|
||||
ahc_echo (void *cls,
|
||||
@@ -39,23 +40,23 @@ ahc_echo (void *cls,
|
||||
const char *me = cls;
|
||||
struct MHD_Response *response;
|
||||
int ret;
|
||||
(void)url; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) url; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 != strcmp (method, "GET"))
|
||||
return MHD_NO; /* unexpected method */
|
||||
if (&aptr != *ptr)
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
*ptr = NULL; /* reset when done */
|
||||
response = MHD_create_response_from_buffer (strlen (me),
|
||||
(void *) me,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
(void *) me,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
@@ -65,27 +66,27 @@ ahc_echo (void *cls,
|
||||
|
||||
static void
|
||||
request_completed (void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
void **con_cls,
|
||||
enum MHD_RequestTerminationCode toe)
|
||||
struct MHD_Connection *connection,
|
||||
void **con_cls,
|
||||
enum MHD_RequestTerminationCode toe)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"%llu - RC: %d\n",
|
||||
(unsigned long long) __rdtsc(),
|
||||
toe);
|
||||
"%llu - RC: %d\n",
|
||||
(unsigned long long) __rdtsc (),
|
||||
toe);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
connection_completed (void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
void **socket_context,
|
||||
enum MHD_ConnectionNotificationCode toe)
|
||||
struct MHD_Connection *connection,
|
||||
void **socket_context,
|
||||
enum MHD_ConnectionNotificationCode toe)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"%llu - CC: %d\n",
|
||||
(unsigned long long) __rdtsc(),
|
||||
toe);
|
||||
"%llu - CC: %d\n",
|
||||
(unsigned long long) __rdtsc (),
|
||||
toe);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,22 +96,23 @@ main (int argc, char *const *argv)
|
||||
struct MHD_Daemon *d;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (/* MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, */
|
||||
/* MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, */
|
||||
/* MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_POLL, */
|
||||
MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_POLL, // | MHD_USE_ITC,
|
||||
/* MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, */
|
||||
atoi (argv[1]),
|
||||
NULL, NULL, &ahc_echo, PAGE,
|
||||
MHD_OPTION_NOTIFY_COMPLETED, &request_completed, NULL,
|
||||
MHD_OPTION_NOTIFY_CONNECTION, &connection_completed, NULL,
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120,
|
||||
MHD_OPTION_STRICT_FOR_CLIENT, (int) 1,
|
||||
MHD_OPTION_END);
|
||||
MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD
|
||||
| MHD_USE_ERROR_LOG | MHD_USE_POLL, // | MHD_USE_ITC,
|
||||
/* MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, */
|
||||
atoi (argv[1]),
|
||||
NULL, NULL, &ahc_echo, PAGE,
|
||||
MHD_OPTION_NOTIFY_COMPLETED, &request_completed, NULL,
|
||||
MHD_OPTION_NOTIFY_CONNECTION, &connection_completed, NULL,
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120,
|
||||
MHD_OPTION_STRICT_FOR_CLIENT, (int) 1,
|
||||
MHD_OPTION_END);
|
||||
if (d == NULL)
|
||||
return 1;
|
||||
(void) getc (stdin);
|
||||
|
||||
+383
-369
@@ -41,10 +41,10 @@
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if defined(CPU_COUNT) && (CPU_COUNT+0) < 2
|
||||
#if defined(CPU_COUNT) && (CPU_COUNT + 0) < 2
|
||||
#undef CPU_COUNT
|
||||
#endif
|
||||
#if !defined(CPU_COUNT)
|
||||
#if ! defined(CPU_COUNT)
|
||||
#define CPU_COUNT 2
|
||||
#endif
|
||||
|
||||
@@ -73,46 +73,50 @@
|
||||
/**
|
||||
* Page returned for file-not-found.
|
||||
*/
|
||||
#define FILE_NOT_FOUND_PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"
|
||||
#define FILE_NOT_FOUND_PAGE \
|
||||
"<html><head><title>File not found</title></head><body>File not found</body></html>"
|
||||
|
||||
|
||||
/**
|
||||
* Page returned for internal errors.
|
||||
*/
|
||||
#define INTERNAL_ERROR_PAGE "<html><head><title>Internal error</title></head><body>Internal error</body></html>"
|
||||
#define INTERNAL_ERROR_PAGE \
|
||||
"<html><head><title>Internal error</title></head><body>Internal error</body></html>"
|
||||
|
||||
|
||||
/**
|
||||
* Page returned for refused requests.
|
||||
*/
|
||||
#define REQUEST_REFUSED_PAGE "<html><head><title>Request refused</title></head><body>Request refused (file exists?)</body></html>"
|
||||
#define REQUEST_REFUSED_PAGE \
|
||||
"<html><head><title>Request refused</title></head><body>Request refused (file exists?)</body></html>"
|
||||
|
||||
|
||||
/**
|
||||
* Head of index page.
|
||||
*/
|
||||
#define INDEX_PAGE_HEADER "<html>\n<head><title>Welcome</title></head>\n<body>\n"\
|
||||
"<h1>Upload</h1>\n"\
|
||||
"<form method=\"POST\" enctype=\"multipart/form-data\" action=\"/\">\n"\
|
||||
"<dl><dt>Content type:</dt><dd>"\
|
||||
"<input type=\"radio\" name=\"category\" value=\"books\">Book</input>"\
|
||||
"<input type=\"radio\" name=\"category\" value=\"images\">Image</input>"\
|
||||
"<input type=\"radio\" name=\"category\" value=\"music\">Music</input>"\
|
||||
"<input type=\"radio\" name=\"category\" value=\"software\">Software</input>"\
|
||||
"<input type=\"radio\" name=\"category\" value=\"videos\">Videos</input>\n"\
|
||||
"<input type=\"radio\" name=\"category\" value=\"other\" checked>Other</input></dd>"\
|
||||
"<dt>Language:</dt><dd>"\
|
||||
"<input type=\"radio\" name=\"language\" value=\"no-lang\" checked>none</input>"\
|
||||
"<input type=\"radio\" name=\"language\" value=\"en\">English</input>"\
|
||||
"<input type=\"radio\" name=\"language\" value=\"de\">German</input>"\
|
||||
"<input type=\"radio\" name=\"language\" value=\"fr\">French</input>"\
|
||||
"<input type=\"radio\" name=\"language\" value=\"es\">Spanish</input></dd>\n"\
|
||||
"<dt>File:</dt><dd>"\
|
||||
"<input type=\"file\" name=\"upload\"/></dd></dl>"\
|
||||
"<input type=\"submit\" value=\"Send!\"/>\n"\
|
||||
"</form>\n"\
|
||||
"<h1>Download</h1>\n"\
|
||||
"<ol>\n"
|
||||
#define INDEX_PAGE_HEADER \
|
||||
"<html>\n<head><title>Welcome</title></head>\n<body>\n" \
|
||||
"<h1>Upload</h1>\n" \
|
||||
"<form method=\"POST\" enctype=\"multipart/form-data\" action=\"/\">\n" \
|
||||
"<dl><dt>Content type:</dt><dd>" \
|
||||
"<input type=\"radio\" name=\"category\" value=\"books\">Book</input>" \
|
||||
"<input type=\"radio\" name=\"category\" value=\"images\">Image</input>" \
|
||||
"<input type=\"radio\" name=\"category\" value=\"music\">Music</input>" \
|
||||
"<input type=\"radio\" name=\"category\" value=\"software\">Software</input>" \
|
||||
"<input type=\"radio\" name=\"category\" value=\"videos\">Videos</input>\n" \
|
||||
"<input type=\"radio\" name=\"category\" value=\"other\" checked>Other</input></dd>" \
|
||||
"<dt>Language:</dt><dd>" \
|
||||
"<input type=\"radio\" name=\"language\" value=\"no-lang\" checked>none</input>" \
|
||||
"<input type=\"radio\" name=\"language\" value=\"en\">English</input>" \
|
||||
"<input type=\"radio\" name=\"language\" value=\"de\">German</input>" \
|
||||
"<input type=\"radio\" name=\"language\" value=\"fr\">French</input>" \
|
||||
"<input type=\"radio\" name=\"language\" value=\"es\">Spanish</input></dd>\n" \
|
||||
"<dt>File:</dt><dd>" \
|
||||
"<input type=\"file\" name=\"upload\"/></dd></dl>" \
|
||||
"<input type=\"submit\" value=\"Send!\"/>\n" \
|
||||
"</form>\n" \
|
||||
"<h1>Download</h1>\n" \
|
||||
"<ol>\n"
|
||||
|
||||
/**
|
||||
* Footer of index page.
|
||||
@@ -124,16 +128,15 @@
|
||||
* NULL-terminated array of supported upload categories. Should match HTML
|
||||
* in the form.
|
||||
*/
|
||||
static const char * const categories[] =
|
||||
{
|
||||
"books",
|
||||
"images",
|
||||
"music",
|
||||
"software",
|
||||
"videos",
|
||||
"other",
|
||||
NULL,
|
||||
};
|
||||
static const char *const categories[] = {
|
||||
"books",
|
||||
"images",
|
||||
"music",
|
||||
"software",
|
||||
"videos",
|
||||
"other",
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@@ -157,15 +160,14 @@ struct Language
|
||||
* NULL-terminated array of supported upload categories. Should match HTML
|
||||
* in the form.
|
||||
*/
|
||||
static const struct Language languages[] =
|
||||
{
|
||||
{ "no-lang", "No language specified" },
|
||||
{ "en", "English" },
|
||||
{ "de", "German" },
|
||||
{ "fr", "French" },
|
||||
{ "es", "Spanish" },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
static const struct Language languages[] = {
|
||||
{ "no-lang", "No language specified" },
|
||||
{ "en", "English" },
|
||||
{ "de", "German" },
|
||||
{ "fr", "French" },
|
||||
{ "es", "Spanish" },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@@ -210,8 +212,8 @@ static void
|
||||
mark_as_html (struct MHD_Response *response)
|
||||
{
|
||||
(void) MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_TYPE,
|
||||
"text/html");
|
||||
MHD_HTTP_HEADER_CONTENT_TYPE,
|
||||
"text/html");
|
||||
}
|
||||
|
||||
|
||||
@@ -264,7 +266,7 @@ struct ResponseDataContext
|
||||
*/
|
||||
static int
|
||||
list_directory (struct ResponseDataContext *rdc,
|
||||
const char *dirname)
|
||||
const char *dirname)
|
||||
{
|
||||
char fullname[PATH_MAX];
|
||||
struct stat sbuf;
|
||||
@@ -274,35 +276,35 @@ list_directory (struct ResponseDataContext *rdc,
|
||||
if (NULL == (dir = opendir (dirname)))
|
||||
return MHD_NO;
|
||||
while (NULL != (de = readdir (dir)))
|
||||
{
|
||||
if ('.' == de->d_name[0])
|
||||
continue;
|
||||
if (sizeof (fullname) <= (unsigned int)
|
||||
snprintf (fullname, sizeof (fullname),
|
||||
"%s/%s",
|
||||
dirname, de->d_name))
|
||||
continue; /* ugh, file too long? how can this be!? */
|
||||
if (0 != stat (fullname, &sbuf))
|
||||
continue; /* ugh, failed to 'stat' */
|
||||
if (! S_ISREG (sbuf.st_mode))
|
||||
continue; /* not a regular file, skip */
|
||||
if (rdc->off + 1024 > rdc->buf_len)
|
||||
{
|
||||
if ('.' == de->d_name[0])
|
||||
continue;
|
||||
if (sizeof (fullname) <= (unsigned int)
|
||||
snprintf (fullname, sizeof (fullname),
|
||||
"%s/%s",
|
||||
dirname, de->d_name))
|
||||
continue; /* ugh, file too long? how can this be!? */
|
||||
if (0 != stat (fullname, &sbuf))
|
||||
continue; /* ugh, failed to 'stat' */
|
||||
if (! S_ISREG (sbuf.st_mode))
|
||||
continue; /* not a regular file, skip */
|
||||
if (rdc->off + 1024 > rdc->buf_len)
|
||||
{
|
||||
void *r;
|
||||
void *r;
|
||||
|
||||
if ( (2 * rdc->buf_len + 1024) < rdc->buf_len)
|
||||
break; /* more than SIZE_T _index_ size? Too big for us */
|
||||
rdc->buf_len = 2 * rdc->buf_len + 1024;
|
||||
if (NULL == (r = realloc (rdc->buf, rdc->buf_len)))
|
||||
break; /* out of memory */
|
||||
rdc->buf = r;
|
||||
}
|
||||
rdc->off += snprintf (&rdc->buf[rdc->off],
|
||||
rdc->buf_len - rdc->off,
|
||||
"<li><a href=\"/%s\">%s</a></li>\n",
|
||||
fullname,
|
||||
de->d_name);
|
||||
if ( (2 * rdc->buf_len + 1024) < rdc->buf_len)
|
||||
break; /* more than SIZE_T _index_ size? Too big for us */
|
||||
rdc->buf_len = 2 * rdc->buf_len + 1024;
|
||||
if (NULL == (r = realloc (rdc->buf, rdc->buf_len)))
|
||||
break; /* out of memory */
|
||||
rdc->buf = r;
|
||||
}
|
||||
rdc->off += snprintf (&rdc->buf[rdc->off],
|
||||
rdc->buf_len - rdc->off,
|
||||
"<li><a href=\"/%s\">%s</a></li>\n",
|
||||
fullname,
|
||||
de->d_name);
|
||||
}
|
||||
(void) closedir (dir);
|
||||
return MHD_YES;
|
||||
}
|
||||
@@ -326,65 +328,66 @@ update_directory ()
|
||||
|
||||
rdc.buf_len = initial_allocation;
|
||||
if (NULL == (rdc.buf = malloc (rdc.buf_len)))
|
||||
{
|
||||
update_cached_response (NULL);
|
||||
return;
|
||||
}
|
||||
{
|
||||
update_cached_response (NULL);
|
||||
return;
|
||||
}
|
||||
rdc.off = snprintf (rdc.buf, rdc.buf_len,
|
||||
"%s",
|
||||
INDEX_PAGE_HEADER);
|
||||
for (language_idx = 0; NULL != languages[language_idx].dirname; language_idx++)
|
||||
"%s",
|
||||
INDEX_PAGE_HEADER);
|
||||
for (language_idx = 0; NULL != languages[language_idx].dirname;
|
||||
language_idx++)
|
||||
{
|
||||
language = &languages[language_idx];
|
||||
|
||||
if (0 != stat (language->dirname, &sbuf))
|
||||
continue; /* empty */
|
||||
/* we ensured always +1k room, filenames are ~256 bytes,
|
||||
so there is always still enough space for the header
|
||||
without need for an additional reallocation check. */
|
||||
rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off,
|
||||
"<h2>%s</h2>\n",
|
||||
language->longname);
|
||||
for (category_idx = 0; NULL != categories[category_idx]; category_idx++)
|
||||
{
|
||||
language = &languages[language_idx];
|
||||
category = categories[category_idx];
|
||||
snprintf (dir_name, sizeof (dir_name),
|
||||
"%s/%s",
|
||||
language->dirname,
|
||||
category);
|
||||
if (0 != stat (dir_name, &sbuf))
|
||||
continue; /* empty */
|
||||
|
||||
if (0 != stat (language->dirname, &sbuf))
|
||||
continue; /* empty */
|
||||
/* we ensured always +1k room, filenames are ~256 bytes,
|
||||
so there is always still enough space for the header
|
||||
without need for an additional reallocation check. */
|
||||
so there is always still enough space for the header
|
||||
without need for an additional reallocation check. */
|
||||
rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off,
|
||||
"<h2>%s</h2>\n",
|
||||
language->longname);
|
||||
for (category_idx = 0; NULL != categories[category_idx]; category_idx++)
|
||||
{
|
||||
category = categories[category_idx];
|
||||
snprintf (dir_name, sizeof (dir_name),
|
||||
"%s/%s",
|
||||
language->dirname,
|
||||
category);
|
||||
if (0 != stat (dir_name, &sbuf))
|
||||
continue; /* empty */
|
||||
"<h3>%s</h3>\n",
|
||||
category);
|
||||
|
||||
/* we ensured always +1k room, filenames are ~256 bytes,
|
||||
so there is always still enough space for the header
|
||||
without need for an additional reallocation check. */
|
||||
rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off,
|
||||
"<h3>%s</h3>\n",
|
||||
category);
|
||||
|
||||
if (MHD_NO == list_directory (&rdc, dir_name))
|
||||
{
|
||||
free (rdc.buf);
|
||||
update_cached_response (NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (MHD_NO == list_directory (&rdc, dir_name))
|
||||
{
|
||||
free (rdc.buf);
|
||||
update_cached_response (NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* we ensured always +1k room, filenames are ~256 bytes,
|
||||
so there is always still enough space for the footer
|
||||
without need for a final reallocation check. */
|
||||
rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off,
|
||||
"%s",
|
||||
INDEX_PAGE_FOOTER);
|
||||
"%s",
|
||||
INDEX_PAGE_FOOTER);
|
||||
initial_allocation = rdc.buf_len; /* remember for next time */
|
||||
response = MHD_create_response_from_buffer (rdc.off,
|
||||
rdc.buf,
|
||||
MHD_RESPMEM_MUST_FREE);
|
||||
rdc.buf,
|
||||
MHD_RESPMEM_MUST_FREE);
|
||||
mark_as_html (response);
|
||||
#if FORCE_CLOSE
|
||||
(void) MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"close");
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"close");
|
||||
#endif
|
||||
update_cached_response (response);
|
||||
}
|
||||
@@ -443,8 +446,8 @@ struct UploadContext
|
||||
*/
|
||||
static int
|
||||
do_append (char **ret,
|
||||
const char *data,
|
||||
size_t size)
|
||||
const char *data,
|
||||
size_t size)
|
||||
{
|
||||
char *buf;
|
||||
size_t old_len;
|
||||
@@ -456,15 +459,15 @@ do_append (char **ret,
|
||||
if (NULL == (buf = malloc (old_len + size + 1)))
|
||||
return MHD_NO;
|
||||
if (NULL != *ret)
|
||||
{
|
||||
memcpy (buf,
|
||||
*ret,
|
||||
old_len);
|
||||
free (*ret);
|
||||
}
|
||||
{
|
||||
memcpy (buf,
|
||||
*ret,
|
||||
old_len);
|
||||
free (*ret);
|
||||
}
|
||||
memcpy (&buf[old_len],
|
||||
data,
|
||||
size);
|
||||
data,
|
||||
size);
|
||||
buf[old_len + size] = '\0';
|
||||
*ret = buf;
|
||||
return MHD_YES;
|
||||
@@ -492,119 +495,119 @@ do_append (char **ret,
|
||||
*/
|
||||
static int
|
||||
process_upload_data (void *cls,
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
const char *filename,
|
||||
const char *content_type,
|
||||
const char *transfer_encoding,
|
||||
const char *data,
|
||||
uint64_t off,
|
||||
size_t size)
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
const char *filename,
|
||||
const char *content_type,
|
||||
const char *transfer_encoding,
|
||||
const char *data,
|
||||
uint64_t off,
|
||||
size_t size)
|
||||
{
|
||||
struct UploadContext *uc = cls;
|
||||
int i;
|
||||
(void)kind; /* Unused. Silent compiler warning. */
|
||||
(void)content_type; /* Unused. Silent compiler warning. */
|
||||
(void)transfer_encoding; /* Unused. Silent compiler warning. */
|
||||
(void)off; /* Unused. Silent compiler warning. */
|
||||
(void) kind; /* Unused. Silent compiler warning. */
|
||||
(void) content_type; /* Unused. Silent compiler warning. */
|
||||
(void) transfer_encoding; /* Unused. Silent compiler warning. */
|
||||
(void) off; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 == strcmp (key, "category"))
|
||||
return do_append (&uc->category, data, size);
|
||||
if (0 == strcmp (key, "language"))
|
||||
return do_append (&uc->language, data, size);
|
||||
if (0 != strcmp (key, "upload"))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Ignoring unexpected form value `%s'\n",
|
||||
key);
|
||||
return MHD_YES; /* ignore */
|
||||
}
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Ignoring unexpected form value `%s'\n",
|
||||
key);
|
||||
return MHD_YES; /* ignore */
|
||||
}
|
||||
if (NULL == filename)
|
||||
{
|
||||
fprintf (stderr, "No filename, aborting upload\n");
|
||||
return MHD_NO; /* no filename, error */
|
||||
}
|
||||
{
|
||||
fprintf (stderr, "No filename, aborting upload\n");
|
||||
return MHD_NO; /* no filename, error */
|
||||
}
|
||||
if ( (NULL == uc->category) ||
|
||||
(NULL == uc->language) )
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Missing form data for upload `%s'\n",
|
||||
filename);
|
||||
uc->response = request_refused_response;
|
||||
return MHD_NO;
|
||||
}
|
||||
if (-1 == uc->fd)
|
||||
{
|
||||
char fn[PATH_MAX];
|
||||
|
||||
if ( (NULL != strstr (filename, "..")) ||
|
||||
(NULL != strchr (filename, '/')) ||
|
||||
(NULL != strchr (filename, '\\')) )
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Missing form data for upload `%s'\n",
|
||||
filename);
|
||||
uc->response = request_refused_response;
|
||||
return MHD_NO;
|
||||
}
|
||||
if (-1 == uc->fd)
|
||||
{
|
||||
char fn[PATH_MAX];
|
||||
|
||||
if ( (NULL != strstr (filename, "..")) ||
|
||||
(NULL != strchr (filename, '/')) ||
|
||||
(NULL != strchr (filename, '\\')) )
|
||||
{
|
||||
uc->response = request_refused_response;
|
||||
return MHD_NO;
|
||||
}
|
||||
/* create directories -- if they don't exist already */
|
||||
/* create directories -- if they don't exist already */
|
||||
#ifdef WINDOWS
|
||||
(void) mkdir (uc->language);
|
||||
(void) mkdir (uc->language);
|
||||
#else
|
||||
(void) mkdir (uc->language, S_IRWXU);
|
||||
(void) mkdir (uc->language, S_IRWXU);
|
||||
#endif
|
||||
snprintf (fn, sizeof (fn),
|
||||
"%s/%s",
|
||||
uc->language,
|
||||
uc->category);
|
||||
snprintf (fn, sizeof (fn),
|
||||
"%s/%s",
|
||||
uc->language,
|
||||
uc->category);
|
||||
#ifdef WINDOWS
|
||||
(void) mkdir (fn);
|
||||
(void) mkdir (fn);
|
||||
#else
|
||||
(void) mkdir (fn, S_IRWXU);
|
||||
(void) mkdir (fn, S_IRWXU);
|
||||
#endif
|
||||
/* open file */
|
||||
snprintf (fn, sizeof (fn),
|
||||
"%s/%s/%s",
|
||||
uc->language,
|
||||
uc->category,
|
||||
filename);
|
||||
for (i=strlen (fn)-1;i>=0;i--)
|
||||
if (! isprint ((unsigned char) fn[i]))
|
||||
fn[i] = '_';
|
||||
uc->fd = open (fn,
|
||||
O_CREAT | O_EXCL
|
||||
/* open file */
|
||||
snprintf (fn, sizeof (fn),
|
||||
"%s/%s/%s",
|
||||
uc->language,
|
||||
uc->category,
|
||||
filename);
|
||||
for (i = strlen (fn) - 1; i>=0; i--)
|
||||
if (! isprint ((unsigned char) fn[i]))
|
||||
fn[i] = '_';
|
||||
uc->fd = open (fn,
|
||||
O_CREAT | O_EXCL
|
||||
#if O_LARGEFILE
|
||||
| O_LARGEFILE
|
||||
| O_LARGEFILE
|
||||
#endif
|
||||
| O_WRONLY,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (-1 == uc->fd)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Error opening file `%s' for upload: %s\n",
|
||||
fn,
|
||||
strerror (errno));
|
||||
uc->response = request_refused_response;
|
||||
return MHD_NO;
|
||||
}
|
||||
uc->filename = strdup (fn);
|
||||
}
|
||||
if ( (0 != size) &&
|
||||
(size != (size_t) write (uc->fd, data, size)) )
|
||||
| O_WRONLY,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (-1 == uc->fd)
|
||||
{
|
||||
/* write failed; likely: disk full */
|
||||
fprintf (stderr,
|
||||
"Error writing to file `%s': %s\n",
|
||||
uc->filename,
|
||||
strerror (errno));
|
||||
uc->response = internal_error_response;
|
||||
(void) close (uc->fd);
|
||||
uc->fd = -1;
|
||||
if (NULL != uc->filename)
|
||||
{
|
||||
unlink (uc->filename);
|
||||
free (uc->filename);
|
||||
uc->filename = NULL;
|
||||
}
|
||||
"Error opening file `%s' for upload: %s\n",
|
||||
fn,
|
||||
strerror (errno));
|
||||
uc->response = request_refused_response;
|
||||
return MHD_NO;
|
||||
}
|
||||
uc->filename = strdup (fn);
|
||||
}
|
||||
if ( (0 != size) &&
|
||||
(size != (size_t) write (uc->fd, data, size)) )
|
||||
{
|
||||
/* write failed; likely: disk full */
|
||||
fprintf (stderr,
|
||||
"Error writing to file `%s': %s\n",
|
||||
uc->filename,
|
||||
strerror (errno));
|
||||
uc->response = internal_error_response;
|
||||
(void) close (uc->fd);
|
||||
uc->fd = -1;
|
||||
if (NULL != uc->filename)
|
||||
{
|
||||
unlink (uc->filename);
|
||||
free (uc->filename);
|
||||
uc->filename = NULL;
|
||||
}
|
||||
return MHD_NO;
|
||||
}
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
@@ -622,32 +625,32 @@ process_upload_data (void *cls,
|
||||
*/
|
||||
static void
|
||||
response_completed_callback (void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
void **con_cls,
|
||||
enum MHD_RequestTerminationCode toe)
|
||||
struct MHD_Connection *connection,
|
||||
void **con_cls,
|
||||
enum MHD_RequestTerminationCode toe)
|
||||
{
|
||||
struct UploadContext *uc = *con_cls;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)connection; /* Unused. Silent compiler warning. */
|
||||
(void)toe; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) connection; /* Unused. Silent compiler warning. */
|
||||
(void) toe; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (NULL == uc)
|
||||
return; /* this request wasn't an upload request */
|
||||
if (NULL != uc->pp)
|
||||
{
|
||||
MHD_destroy_post_processor (uc->pp);
|
||||
uc->pp = NULL;
|
||||
}
|
||||
{
|
||||
MHD_destroy_post_processor (uc->pp);
|
||||
uc->pp = NULL;
|
||||
}
|
||||
if (-1 != uc->fd)
|
||||
{
|
||||
(void) close (uc->fd);
|
||||
if (NULL != uc->filename)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Upload of file `%s' failed (incomplete or aborted), removing file.\n",
|
||||
uc->filename);
|
||||
(void) unlink (uc->filename);
|
||||
}
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Upload of file `%s' failed (incomplete or aborted), removing file.\n",
|
||||
uc->filename);
|
||||
(void) unlink (uc->filename);
|
||||
}
|
||||
}
|
||||
if (NULL != uc->filename)
|
||||
free (uc->filename);
|
||||
@@ -669,12 +672,12 @@ return_directory_response (struct MHD_Connection *connection)
|
||||
(void) pthread_mutex_lock (&mutex);
|
||||
if (NULL == cached_directory_response)
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
internal_error_response);
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
internal_error_response);
|
||||
else
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_OK,
|
||||
cached_directory_response);
|
||||
MHD_HTTP_OK,
|
||||
cached_directory_response);
|
||||
(void) pthread_mutex_unlock (&mutex);
|
||||
return ret;
|
||||
}
|
||||
@@ -695,12 +698,12 @@ return_directory_response (struct MHD_Connection *connection)
|
||||
*/
|
||||
static int
|
||||
generate_page (void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
const char *url,
|
||||
const char *method,
|
||||
const char *version,
|
||||
const char *upload_data,
|
||||
size_t *upload_data_size, void **ptr)
|
||||
struct MHD_Connection *connection,
|
||||
const char *url,
|
||||
const char *method,
|
||||
const char *version,
|
||||
const char *upload_data,
|
||||
size_t *upload_data_size, void **ptr)
|
||||
{
|
||||
struct MHD_Response *response;
|
||||
int ret;
|
||||
@@ -710,117 +713,117 @@ generate_page (void *cls,
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 != strcmp (url, "/"))
|
||||
{
|
||||
/* should be file download */
|
||||
#ifdef MHD_HAVE_LIBMAGIC
|
||||
char file_data[MAGIC_HEADER_SIZE];
|
||||
ssize_t got;
|
||||
#endif /* MHD_HAVE_LIBMAGIC */
|
||||
const char *mime;
|
||||
|
||||
if ( (0 != strcmp (method, MHD_HTTP_METHOD_GET)) &&
|
||||
(0 != strcmp (method, MHD_HTTP_METHOD_HEAD)) )
|
||||
return MHD_NO; /* unexpected method (we're not polite...) */
|
||||
fd = -1;
|
||||
if ( (NULL == strstr (&url[1], "..")) &&
|
||||
('/' != url[1]) )
|
||||
{
|
||||
/* should be file download */
|
||||
#ifdef MHD_HAVE_LIBMAGIC
|
||||
char file_data[MAGIC_HEADER_SIZE];
|
||||
ssize_t got;
|
||||
#endif /* MHD_HAVE_LIBMAGIC */
|
||||
const char *mime;
|
||||
|
||||
if ( (0 != strcmp (method, MHD_HTTP_METHOD_GET)) &&
|
||||
(0 != strcmp (method, MHD_HTTP_METHOD_HEAD)) )
|
||||
return MHD_NO; /* unexpected method (we're not polite...) */
|
||||
fd = -1;
|
||||
if ( (NULL == strstr (&url[1], "..")) &&
|
||||
('/' != url[1]) )
|
||||
{
|
||||
fd = open (&url[1], O_RDONLY);
|
||||
if ( (-1 != fd) &&
|
||||
( (0 != fstat (fd, &buf)) ||
|
||||
(! S_ISREG (buf.st_mode)) ) )
|
||||
{
|
||||
(void) close (fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
if (-1 == fd)
|
||||
return MHD_queue_response (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
file_not_found_response);
|
||||
#ifdef MHD_HAVE_LIBMAGIC
|
||||
/* read beginning of the file to determine mime type */
|
||||
got = read (fd, file_data, sizeof (file_data));
|
||||
(void) lseek (fd, 0, SEEK_SET);
|
||||
if (-1 != got)
|
||||
mime = magic_buffer (magic, file_data, got);
|
||||
else
|
||||
#endif /* MHD_HAVE_LIBMAGIC */
|
||||
mime = NULL;
|
||||
|
||||
if (NULL == (response = MHD_create_response_from_fd (buf.st_size,
|
||||
fd)))
|
||||
{
|
||||
/* internal error (i.e. out of memory) */
|
||||
(void) close (fd);
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
/* add mime type if we had one */
|
||||
if (NULL != mime)
|
||||
(void) MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_TYPE,
|
||||
mime);
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_OK,
|
||||
response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
fd = open (&url[1], O_RDONLY);
|
||||
if ( (-1 != fd) &&
|
||||
( (0 != fstat (fd, &buf)) ||
|
||||
(! S_ISREG (buf.st_mode)) ) )
|
||||
{
|
||||
(void) close (fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
if (-1 == fd)
|
||||
return MHD_queue_response (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
file_not_found_response);
|
||||
#ifdef MHD_HAVE_LIBMAGIC
|
||||
/* read beginning of the file to determine mime type */
|
||||
got = read (fd, file_data, sizeof (file_data));
|
||||
(void) lseek (fd, 0, SEEK_SET);
|
||||
if (-1 != got)
|
||||
mime = magic_buffer (magic, file_data, got);
|
||||
else
|
||||
#endif /* MHD_HAVE_LIBMAGIC */
|
||||
mime = NULL;
|
||||
|
||||
if (NULL == (response = MHD_create_response_from_fd (buf.st_size,
|
||||
fd)))
|
||||
{
|
||||
/* internal error (i.e. out of memory) */
|
||||
(void) close (fd);
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
/* add mime type if we had one */
|
||||
if (NULL != mime)
|
||||
(void) MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_TYPE,
|
||||
mime);
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_OK,
|
||||
response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
|
||||
{
|
||||
/* upload! */
|
||||
struct UploadContext *uc = *ptr;
|
||||
{
|
||||
/* upload! */
|
||||
struct UploadContext *uc = *ptr;
|
||||
|
||||
if (NULL == uc)
|
||||
{
|
||||
if (NULL == (uc = malloc (sizeof (struct UploadContext))))
|
||||
return MHD_NO; /* out of memory, close connection */
|
||||
memset (uc, 0, sizeof (struct UploadContext));
|
||||
uc->fd = -1;
|
||||
uc->connection = connection;
|
||||
uc->pp = MHD_create_post_processor (connection,
|
||||
64 * 1024 /* buffer size */,
|
||||
&process_upload_data, uc);
|
||||
if (NULL == uc->pp)
|
||||
{
|
||||
/* out of memory, close connection */
|
||||
free (uc);
|
||||
return MHD_NO;
|
||||
}
|
||||
*ptr = uc;
|
||||
return MHD_YES;
|
||||
}
|
||||
if (0 != *upload_data_size)
|
||||
{
|
||||
if (NULL == uc->response)
|
||||
(void) MHD_post_process (uc->pp,
|
||||
upload_data,
|
||||
*upload_data_size);
|
||||
*upload_data_size = 0;
|
||||
return MHD_YES;
|
||||
}
|
||||
/* end of upload, finish it! */
|
||||
MHD_destroy_post_processor (uc->pp);
|
||||
uc->pp = NULL;
|
||||
if (-1 != uc->fd)
|
||||
{
|
||||
close (uc->fd);
|
||||
uc->fd = -1;
|
||||
}
|
||||
if (NULL != uc->response)
|
||||
{
|
||||
return MHD_queue_response (connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
uc->response);
|
||||
}
|
||||
else
|
||||
{
|
||||
update_directory ();
|
||||
return return_directory_response (connection);
|
||||
}
|
||||
if (NULL == uc)
|
||||
{
|
||||
if (NULL == (uc = malloc (sizeof (struct UploadContext))))
|
||||
return MHD_NO; /* out of memory, close connection */
|
||||
memset (uc, 0, sizeof (struct UploadContext));
|
||||
uc->fd = -1;
|
||||
uc->connection = connection;
|
||||
uc->pp = MHD_create_post_processor (connection,
|
||||
64 * 1024 /* buffer size */,
|
||||
&process_upload_data, uc);
|
||||
if (NULL == uc->pp)
|
||||
{
|
||||
/* out of memory, close connection */
|
||||
free (uc);
|
||||
return MHD_NO;
|
||||
}
|
||||
*ptr = uc;
|
||||
return MHD_YES;
|
||||
}
|
||||
if (0 != *upload_data_size)
|
||||
{
|
||||
if (NULL == uc->response)
|
||||
(void) MHD_post_process (uc->pp,
|
||||
upload_data,
|
||||
*upload_data_size);
|
||||
*upload_data_size = 0;
|
||||
return MHD_YES;
|
||||
}
|
||||
/* end of upload, finish it! */
|
||||
MHD_destroy_post_processor (uc->pp);
|
||||
uc->pp = NULL;
|
||||
if (-1 != uc->fd)
|
||||
{
|
||||
close (uc->fd);
|
||||
uc->fd = -1;
|
||||
}
|
||||
if (NULL != uc->response)
|
||||
{
|
||||
return MHD_queue_response (connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
uc->response);
|
||||
}
|
||||
else
|
||||
{
|
||||
update_directory ();
|
||||
return return_directory_response (connection);
|
||||
}
|
||||
}
|
||||
if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) ||
|
||||
(0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) )
|
||||
{
|
||||
@@ -829,8 +832,8 @@ generate_page (void *cls,
|
||||
|
||||
/* unexpected request, refuse */
|
||||
return MHD_queue_response (connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
request_refused_response);
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
request_refused_response);
|
||||
}
|
||||
|
||||
|
||||
@@ -843,7 +846,7 @@ generate_page (void *cls,
|
||||
static void
|
||||
catcher (int sig)
|
||||
{
|
||||
(void)sig; /* Unused. Silent compiler warning. */
|
||||
(void) sig; /* Unused. Silent compiler warning. */
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
@@ -889,11 +892,11 @@ main (int argc, char *const *argv)
|
||||
if ( (argc != 2) ||
|
||||
(1 != sscanf (argv[1], "%u", &port)) ||
|
||||
(UINT16_MAX < port) )
|
||||
{
|
||||
fprintf (stderr,
|
||||
"%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
fprintf (stderr,
|
||||
"%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
#ifndef MINGW
|
||||
ignore_sigpipe ();
|
||||
#endif
|
||||
@@ -903,31 +906,42 @@ main (int argc, char *const *argv)
|
||||
#endif /* MHD_HAVE_LIBMAGIC */
|
||||
|
||||
(void) pthread_mutex_init (&mutex, NULL);
|
||||
file_not_found_response = MHD_create_response_from_buffer (strlen (FILE_NOT_FOUND_PAGE),
|
||||
(void *) FILE_NOT_FOUND_PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
file_not_found_response = MHD_create_response_from_buffer (strlen (
|
||||
FILE_NOT_FOUND_PAGE),
|
||||
(void *)
|
||||
FILE_NOT_FOUND_PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
mark_as_html (file_not_found_response);
|
||||
request_refused_response = MHD_create_response_from_buffer (strlen (REQUEST_REFUSED_PAGE),
|
||||
(void *) REQUEST_REFUSED_PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
request_refused_response = MHD_create_response_from_buffer (strlen (
|
||||
REQUEST_REFUSED_PAGE),
|
||||
(void *)
|
||||
REQUEST_REFUSED_PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
mark_as_html (request_refused_response);
|
||||
internal_error_response = MHD_create_response_from_buffer (strlen (INTERNAL_ERROR_PAGE),
|
||||
(void *) INTERNAL_ERROR_PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
internal_error_response = MHD_create_response_from_buffer (strlen (
|
||||
INTERNAL_ERROR_PAGE),
|
||||
(void *)
|
||||
INTERNAL_ERROR_PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
mark_as_html (internal_error_response);
|
||||
update_directory ();
|
||||
d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD
|
||||
| MHD_USE_ERROR_LOG,
|
||||
port,
|
||||
NULL, NULL,
|
||||
&generate_page, NULL,
|
||||
MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (256 * 1024),
|
||||
&generate_page, NULL,
|
||||
MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (256
|
||||
* 1024),
|
||||
#if PRODUCTION
|
||||
MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) (64),
|
||||
MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) (64),
|
||||
#endif
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) (120 /* seconds */),
|
||||
MHD_OPTION_THREAD_POOL_SIZE, (unsigned int) NUMBER_OF_THREADS,
|
||||
MHD_OPTION_NOTIFY_COMPLETED, &response_completed_callback, NULL,
|
||||
MHD_OPTION_END);
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned
|
||||
int) (120 /* seconds */),
|
||||
MHD_OPTION_THREAD_POOL_SIZE, (unsigned
|
||||
int) NUMBER_OF_THREADS,
|
||||
MHD_OPTION_NOTIFY_COMPLETED,
|
||||
&response_completed_callback, NULL,
|
||||
MHD_OPTION_END);
|
||||
if (NULL == d)
|
||||
return 1;
|
||||
fprintf (stderr, "HTTP server running. Press ENTER to stop the server\n");
|
||||
|
||||
+432
-418
@@ -44,10 +44,10 @@
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if defined(CPU_COUNT) && (CPU_COUNT+0) < 2
|
||||
#if defined(CPU_COUNT) && (CPU_COUNT + 0) < 2
|
||||
#undef CPU_COUNT
|
||||
#endif
|
||||
#if !defined(CPU_COUNT)
|
||||
#if ! defined(CPU_COUNT)
|
||||
#define CPU_COUNT 2
|
||||
#endif
|
||||
|
||||
@@ -76,46 +76,50 @@
|
||||
/**
|
||||
* Page returned for file-not-found.
|
||||
*/
|
||||
#define FILE_NOT_FOUND_PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"
|
||||
#define FILE_NOT_FOUND_PAGE \
|
||||
"<html><head><title>File not found</title></head><body>File not found</body></html>"
|
||||
|
||||
|
||||
/**
|
||||
* Page returned for internal errors.
|
||||
*/
|
||||
#define INTERNAL_ERROR_PAGE "<html><head><title>Internal error</title></head><body>Internal error</body></html>"
|
||||
#define INTERNAL_ERROR_PAGE \
|
||||
"<html><head><title>Internal error</title></head><body>Internal error</body></html>"
|
||||
|
||||
|
||||
/**
|
||||
* Page returned for refused requests.
|
||||
*/
|
||||
#define REQUEST_REFUSED_PAGE "<html><head><title>Request refused</title></head><body>Request refused (file exists?)</body></html>"
|
||||
#define REQUEST_REFUSED_PAGE \
|
||||
"<html><head><title>Request refused</title></head><body>Request refused (file exists?)</body></html>"
|
||||
|
||||
|
||||
/**
|
||||
* Head of index page.
|
||||
*/
|
||||
#define INDEX_PAGE_HEADER "<html>\n<head><title>Welcome</title></head>\n<body>\n"\
|
||||
"<h1>Upload</h1>\n"\
|
||||
"<form method=\"POST\" enctype=\"multipart/form-data\" action=\"/\">\n"\
|
||||
"<dl><dt>Content type:</dt><dd>"\
|
||||
"<input type=\"radio\" name=\"category\" value=\"books\">Book</input>"\
|
||||
"<input type=\"radio\" name=\"category\" value=\"images\">Image</input>"\
|
||||
"<input type=\"radio\" name=\"category\" value=\"music\">Music</input>"\
|
||||
"<input type=\"radio\" name=\"category\" value=\"software\">Software</input>"\
|
||||
"<input type=\"radio\" name=\"category\" value=\"videos\">Videos</input>\n"\
|
||||
"<input type=\"radio\" name=\"category\" value=\"other\" checked>Other</input></dd>"\
|
||||
"<dt>Language:</dt><dd>"\
|
||||
"<input type=\"radio\" name=\"language\" value=\"no-lang\" checked>none</input>"\
|
||||
"<input type=\"radio\" name=\"language\" value=\"en\">English</input>"\
|
||||
"<input type=\"radio\" name=\"language\" value=\"de\">German</input>"\
|
||||
"<input type=\"radio\" name=\"language\" value=\"fr\">French</input>"\
|
||||
"<input type=\"radio\" name=\"language\" value=\"es\">Spanish</input></dd>\n"\
|
||||
"<dt>File:</dt><dd>"\
|
||||
"<input type=\"file\" name=\"upload\"/></dd></dl>"\
|
||||
"<input type=\"submit\" value=\"Send!\"/>\n"\
|
||||
"</form>\n"\
|
||||
"<h1>Download</h1>\n"\
|
||||
"<ol>\n"
|
||||
#define INDEX_PAGE_HEADER \
|
||||
"<html>\n<head><title>Welcome</title></head>\n<body>\n" \
|
||||
"<h1>Upload</h1>\n" \
|
||||
"<form method=\"POST\" enctype=\"multipart/form-data\" action=\"/\">\n" \
|
||||
"<dl><dt>Content type:</dt><dd>" \
|
||||
"<input type=\"radio\" name=\"category\" value=\"books\">Book</input>" \
|
||||
"<input type=\"radio\" name=\"category\" value=\"images\">Image</input>" \
|
||||
"<input type=\"radio\" name=\"category\" value=\"music\">Music</input>" \
|
||||
"<input type=\"radio\" name=\"category\" value=\"software\">Software</input>" \
|
||||
"<input type=\"radio\" name=\"category\" value=\"videos\">Videos</input>\n" \
|
||||
"<input type=\"radio\" name=\"category\" value=\"other\" checked>Other</input></dd>" \
|
||||
"<dt>Language:</dt><dd>" \
|
||||
"<input type=\"radio\" name=\"language\" value=\"no-lang\" checked>none</input>" \
|
||||
"<input type=\"radio\" name=\"language\" value=\"en\">English</input>" \
|
||||
"<input type=\"radio\" name=\"language\" value=\"de\">German</input>" \
|
||||
"<input type=\"radio\" name=\"language\" value=\"fr\">French</input>" \
|
||||
"<input type=\"radio\" name=\"language\" value=\"es\">Spanish</input></dd>\n" \
|
||||
"<dt>File:</dt><dd>" \
|
||||
"<input type=\"file\" name=\"upload\"/></dd></dl>" \
|
||||
"<input type=\"submit\" value=\"Send!\"/>\n" \
|
||||
"</form>\n" \
|
||||
"<h1>Download</h1>\n" \
|
||||
"<ol>\n"
|
||||
|
||||
/**
|
||||
* Footer of index page.
|
||||
@@ -127,16 +131,15 @@
|
||||
* NULL-terminated array of supported upload categories. Should match HTML
|
||||
* in the form.
|
||||
*/
|
||||
static const char * const categories[] =
|
||||
{
|
||||
"books",
|
||||
"images",
|
||||
"music",
|
||||
"software",
|
||||
"videos",
|
||||
"other",
|
||||
NULL,
|
||||
};
|
||||
static const char *const categories[] = {
|
||||
"books",
|
||||
"images",
|
||||
"music",
|
||||
"software",
|
||||
"videos",
|
||||
"other",
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@@ -160,15 +163,14 @@ struct Language
|
||||
* NULL-terminated array of supported upload categories. Should match HTML
|
||||
* in the form.
|
||||
*/
|
||||
static const struct Language languages[] =
|
||||
{
|
||||
{ "no-lang", "No language specified" },
|
||||
{ "en", "English" },
|
||||
{ "de", "German" },
|
||||
{ "fr", "French" },
|
||||
{ "es", "Spanish" },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
static const struct Language languages[] = {
|
||||
{ "no-lang", "No language specified" },
|
||||
{ "en", "English" },
|
||||
{ "de", "German" },
|
||||
{ "fr", "French" },
|
||||
{ "es", "Spanish" },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@@ -213,8 +215,8 @@ static void
|
||||
mark_as_html (struct MHD_Response *response)
|
||||
{
|
||||
(void) MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_TYPE,
|
||||
"text/html");
|
||||
MHD_HTTP_HEADER_CONTENT_TYPE,
|
||||
"text/html");
|
||||
}
|
||||
|
||||
|
||||
@@ -267,7 +269,7 @@ struct ResponseDataContext
|
||||
*/
|
||||
static int
|
||||
list_directory (struct ResponseDataContext *rdc,
|
||||
const char *dirname)
|
||||
const char *dirname)
|
||||
{
|
||||
char fullname[PATH_MAX];
|
||||
struct stat sbuf;
|
||||
@@ -277,35 +279,35 @@ list_directory (struct ResponseDataContext *rdc,
|
||||
if (NULL == (dir = opendir (dirname)))
|
||||
return MHD_NO;
|
||||
while (NULL != (de = readdir (dir)))
|
||||
{
|
||||
if ('.' == de->d_name[0])
|
||||
continue;
|
||||
if (sizeof (fullname) <= (size_t)
|
||||
snprintf (fullname, sizeof (fullname),
|
||||
"%s/%s",
|
||||
dirname, de->d_name))
|
||||
continue; /* ugh, file too long? how can this be!? */
|
||||
if (0 != stat (fullname, &sbuf))
|
||||
continue; /* ugh, failed to 'stat' */
|
||||
if (! S_ISREG (sbuf.st_mode))
|
||||
continue; /* not a regular file, skip */
|
||||
if (rdc->off + 1024 > rdc->buf_len)
|
||||
{
|
||||
if ('.' == de->d_name[0])
|
||||
continue;
|
||||
if (sizeof (fullname) <= (size_t)
|
||||
snprintf (fullname, sizeof (fullname),
|
||||
"%s/%s",
|
||||
dirname, de->d_name))
|
||||
continue; /* ugh, file too long? how can this be!? */
|
||||
if (0 != stat (fullname, &sbuf))
|
||||
continue; /* ugh, failed to 'stat' */
|
||||
if (! S_ISREG (sbuf.st_mode))
|
||||
continue; /* not a regular file, skip */
|
||||
if (rdc->off + 1024 > rdc->buf_len)
|
||||
{
|
||||
void *r;
|
||||
void *r;
|
||||
|
||||
if ( (2 * rdc->buf_len + 1024) < rdc->buf_len)
|
||||
break; /* more than SIZE_T _index_ size? Too big for us */
|
||||
rdc->buf_len = 2 * rdc->buf_len + 1024;
|
||||
if (NULL == (r = realloc (rdc->buf, rdc->buf_len)))
|
||||
break; /* out of memory */
|
||||
rdc->buf = r;
|
||||
}
|
||||
rdc->off += snprintf (&rdc->buf[rdc->off],
|
||||
rdc->buf_len - rdc->off,
|
||||
"<li><a href=\"/%s\">%s</a></li>\n",
|
||||
fullname,
|
||||
de->d_name);
|
||||
if ( (2 * rdc->buf_len + 1024) < rdc->buf_len)
|
||||
break; /* more than SIZE_T _index_ size? Too big for us */
|
||||
rdc->buf_len = 2 * rdc->buf_len + 1024;
|
||||
if (NULL == (r = realloc (rdc->buf, rdc->buf_len)))
|
||||
break; /* out of memory */
|
||||
rdc->buf = r;
|
||||
}
|
||||
rdc->off += snprintf (&rdc->buf[rdc->off],
|
||||
rdc->buf_len - rdc->off,
|
||||
"<li><a href=\"/%s\">%s</a></li>\n",
|
||||
fullname,
|
||||
de->d_name);
|
||||
}
|
||||
(void) closedir (dir);
|
||||
return MHD_YES;
|
||||
}
|
||||
@@ -329,65 +331,66 @@ update_directory ()
|
||||
|
||||
rdc.buf_len = initial_allocation;
|
||||
if (NULL == (rdc.buf = malloc (rdc.buf_len)))
|
||||
{
|
||||
update_cached_response (NULL);
|
||||
return;
|
||||
}
|
||||
{
|
||||
update_cached_response (NULL);
|
||||
return;
|
||||
}
|
||||
rdc.off = snprintf (rdc.buf, rdc.buf_len,
|
||||
"%s",
|
||||
INDEX_PAGE_HEADER);
|
||||
for (language_idx = 0; NULL != languages[language_idx].dirname; language_idx++)
|
||||
"%s",
|
||||
INDEX_PAGE_HEADER);
|
||||
for (language_idx = 0; NULL != languages[language_idx].dirname;
|
||||
language_idx++)
|
||||
{
|
||||
language = &languages[language_idx];
|
||||
|
||||
if (0 != stat (language->dirname, &sbuf))
|
||||
continue; /* empty */
|
||||
/* we ensured always +1k room, filenames are ~256 bytes,
|
||||
so there is always still enough space for the header
|
||||
without need for an additional reallocation check. */
|
||||
rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off,
|
||||
"<h2>%s</h2>\n",
|
||||
language->longname);
|
||||
for (category_idx = 0; NULL != categories[category_idx]; category_idx++)
|
||||
{
|
||||
language = &languages[language_idx];
|
||||
category = categories[category_idx];
|
||||
snprintf (dir_name, sizeof (dir_name),
|
||||
"%s/%s",
|
||||
language->dirname,
|
||||
category);
|
||||
if (0 != stat (dir_name, &sbuf))
|
||||
continue; /* empty */
|
||||
|
||||
if (0 != stat (language->dirname, &sbuf))
|
||||
continue; /* empty */
|
||||
/* we ensured always +1k room, filenames are ~256 bytes,
|
||||
so there is always still enough space for the header
|
||||
without need for an additional reallocation check. */
|
||||
so there is always still enough space for the header
|
||||
without need for an additional reallocation check. */
|
||||
rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off,
|
||||
"<h2>%s</h2>\n",
|
||||
language->longname);
|
||||
for (category_idx = 0; NULL != categories[category_idx]; category_idx++)
|
||||
{
|
||||
category = categories[category_idx];
|
||||
snprintf (dir_name, sizeof (dir_name),
|
||||
"%s/%s",
|
||||
language->dirname,
|
||||
category);
|
||||
if (0 != stat (dir_name, &sbuf))
|
||||
continue; /* empty */
|
||||
"<h3>%s</h3>\n",
|
||||
category);
|
||||
|
||||
/* we ensured always +1k room, filenames are ~256 bytes,
|
||||
so there is always still enough space for the header
|
||||
without need for an additional reallocation check. */
|
||||
rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off,
|
||||
"<h3>%s</h3>\n",
|
||||
category);
|
||||
|
||||
if (MHD_NO == list_directory (&rdc, dir_name))
|
||||
{
|
||||
free (rdc.buf);
|
||||
update_cached_response (NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (MHD_NO == list_directory (&rdc, dir_name))
|
||||
{
|
||||
free (rdc.buf);
|
||||
update_cached_response (NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* we ensured always +1k room, filenames are ~256 bytes,
|
||||
so there is always still enough space for the footer
|
||||
without need for a final reallocation check. */
|
||||
rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off,
|
||||
"%s",
|
||||
INDEX_PAGE_FOOTER);
|
||||
"%s",
|
||||
INDEX_PAGE_FOOTER);
|
||||
initial_allocation = rdc.buf_len; /* remember for next time */
|
||||
response = MHD_create_response_from_buffer (rdc.off,
|
||||
rdc.buf,
|
||||
MHD_RESPMEM_MUST_FREE);
|
||||
rdc.buf,
|
||||
MHD_RESPMEM_MUST_FREE);
|
||||
mark_as_html (response);
|
||||
#if FORCE_CLOSE
|
||||
(void) MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"close");
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"close");
|
||||
#endif
|
||||
update_cached_response (response);
|
||||
}
|
||||
@@ -446,8 +449,8 @@ struct UploadContext
|
||||
*/
|
||||
static int
|
||||
do_append (char **ret,
|
||||
const char *data,
|
||||
size_t size)
|
||||
const char *data,
|
||||
size_t size)
|
||||
{
|
||||
char *buf;
|
||||
size_t old_len;
|
||||
@@ -459,15 +462,15 @@ do_append (char **ret,
|
||||
if (NULL == (buf = malloc (old_len + size + 1)))
|
||||
return MHD_NO;
|
||||
if (NULL != *ret)
|
||||
{
|
||||
memcpy (buf,
|
||||
*ret,
|
||||
old_len);
|
||||
free (*ret);
|
||||
}
|
||||
{
|
||||
memcpy (buf,
|
||||
*ret,
|
||||
old_len);
|
||||
free (*ret);
|
||||
}
|
||||
memcpy (&buf[old_len],
|
||||
data,
|
||||
size);
|
||||
data,
|
||||
size);
|
||||
buf[old_len + size] = '\0';
|
||||
*ret = buf;
|
||||
return MHD_YES;
|
||||
@@ -495,119 +498,119 @@ do_append (char **ret,
|
||||
*/
|
||||
static int
|
||||
process_upload_data (void *cls,
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
const char *filename,
|
||||
const char *content_type,
|
||||
const char *transfer_encoding,
|
||||
const char *data,
|
||||
uint64_t off,
|
||||
size_t size)
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
const char *filename,
|
||||
const char *content_type,
|
||||
const char *transfer_encoding,
|
||||
const char *data,
|
||||
uint64_t off,
|
||||
size_t size)
|
||||
{
|
||||
struct UploadContext *uc = cls;
|
||||
int i;
|
||||
(void)kind; /* Unused. Silent compiler warning. */
|
||||
(void)content_type; /* Unused. Silent compiler warning. */
|
||||
(void)transfer_encoding; /* Unused. Silent compiler warning. */
|
||||
(void)off; /* Unused. Silent compiler warning. */
|
||||
(void) kind; /* Unused. Silent compiler warning. */
|
||||
(void) content_type; /* Unused. Silent compiler warning. */
|
||||
(void) transfer_encoding; /* Unused. Silent compiler warning. */
|
||||
(void) off; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 == strcmp (key, "category"))
|
||||
return do_append (&uc->category, data, size);
|
||||
if (0 == strcmp (key, "language"))
|
||||
return do_append (&uc->language, data, size);
|
||||
if (0 != strcmp (key, "upload"))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Ignoring unexpected form value `%s'\n",
|
||||
key);
|
||||
return MHD_YES; /* ignore */
|
||||
}
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Ignoring unexpected form value `%s'\n",
|
||||
key);
|
||||
return MHD_YES; /* ignore */
|
||||
}
|
||||
if (NULL == filename)
|
||||
{
|
||||
fprintf (stderr, "No filename, aborting upload\n");
|
||||
return MHD_NO; /* no filename, error */
|
||||
}
|
||||
{
|
||||
fprintf (stderr, "No filename, aborting upload\n");
|
||||
return MHD_NO; /* no filename, error */
|
||||
}
|
||||
if ( (NULL == uc->category) ||
|
||||
(NULL == uc->language) )
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Missing form data for upload `%s'\n",
|
||||
filename);
|
||||
uc->response = request_refused_response;
|
||||
return MHD_NO;
|
||||
}
|
||||
if (-1 == uc->fd)
|
||||
{
|
||||
char fn[PATH_MAX];
|
||||
|
||||
if ( (NULL != strstr (filename, "..")) ||
|
||||
(NULL != strchr (filename, '/')) ||
|
||||
(NULL != strchr (filename, '\\')) )
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Missing form data for upload `%s'\n",
|
||||
filename);
|
||||
uc->response = request_refused_response;
|
||||
return MHD_NO;
|
||||
}
|
||||
if (-1 == uc->fd)
|
||||
{
|
||||
char fn[PATH_MAX];
|
||||
|
||||
if ( (NULL != strstr (filename, "..")) ||
|
||||
(NULL != strchr (filename, '/')) ||
|
||||
(NULL != strchr (filename, '\\')) )
|
||||
{
|
||||
uc->response = request_refused_response;
|
||||
return MHD_NO;
|
||||
}
|
||||
/* create directories -- if they don't exist already */
|
||||
/* create directories -- if they don't exist already */
|
||||
#ifdef WINDOWS
|
||||
(void) mkdir (uc->language);
|
||||
(void) mkdir (uc->language);
|
||||
#else
|
||||
(void) mkdir (uc->language, S_IRWXU);
|
||||
(void) mkdir (uc->language, S_IRWXU);
|
||||
#endif
|
||||
snprintf (fn, sizeof (fn),
|
||||
"%s/%s",
|
||||
uc->language,
|
||||
uc->category);
|
||||
snprintf (fn, sizeof (fn),
|
||||
"%s/%s",
|
||||
uc->language,
|
||||
uc->category);
|
||||
#ifdef WINDOWS
|
||||
(void) mkdir (fn);
|
||||
(void) mkdir (fn);
|
||||
#else
|
||||
(void) mkdir (fn, S_IRWXU);
|
||||
(void) mkdir (fn, S_IRWXU);
|
||||
#endif
|
||||
/* open file */
|
||||
snprintf (fn, sizeof (fn),
|
||||
"%s/%s/%s",
|
||||
uc->language,
|
||||
uc->category,
|
||||
filename);
|
||||
for (i=strlen (fn)-1;i>=0;i--)
|
||||
if (! isprint ((unsigned char) fn[i]))
|
||||
fn[i] = '_';
|
||||
uc->fd = open (fn,
|
||||
O_CREAT | O_EXCL
|
||||
/* open file */
|
||||
snprintf (fn, sizeof (fn),
|
||||
"%s/%s/%s",
|
||||
uc->language,
|
||||
uc->category,
|
||||
filename);
|
||||
for (i = strlen (fn) - 1; i>=0; i--)
|
||||
if (! isprint ((unsigned char) fn[i]))
|
||||
fn[i] = '_';
|
||||
uc->fd = open (fn,
|
||||
O_CREAT | O_EXCL
|
||||
#if O_LARGEFILE
|
||||
| O_LARGEFILE
|
||||
| O_LARGEFILE
|
||||
#endif
|
||||
| O_WRONLY,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (-1 == uc->fd)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Error opening file `%s' for upload: %s\n",
|
||||
fn,
|
||||
strerror (errno));
|
||||
uc->response = request_refused_response;
|
||||
return MHD_NO;
|
||||
}
|
||||
uc->filename = strdup (fn);
|
||||
}
|
||||
if ( (0 != size) &&
|
||||
(size != (size_t) write (uc->fd, data, size)) )
|
||||
| O_WRONLY,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (-1 == uc->fd)
|
||||
{
|
||||
/* write failed; likely: disk full */
|
||||
fprintf (stderr,
|
||||
"Error writing to file `%s': %s\n",
|
||||
uc->filename,
|
||||
strerror (errno));
|
||||
uc->response = internal_error_response;
|
||||
close (uc->fd);
|
||||
uc->fd = -1;
|
||||
if (NULL != uc->filename)
|
||||
{
|
||||
unlink (uc->filename);
|
||||
free (uc->filename);
|
||||
uc->filename = NULL;
|
||||
}
|
||||
"Error opening file `%s' for upload: %s\n",
|
||||
fn,
|
||||
strerror (errno));
|
||||
uc->response = request_refused_response;
|
||||
return MHD_NO;
|
||||
}
|
||||
uc->filename = strdup (fn);
|
||||
}
|
||||
if ( (0 != size) &&
|
||||
(size != (size_t) write (uc->fd, data, size)) )
|
||||
{
|
||||
/* write failed; likely: disk full */
|
||||
fprintf (stderr,
|
||||
"Error writing to file `%s': %s\n",
|
||||
uc->filename,
|
||||
strerror (errno));
|
||||
uc->response = internal_error_response;
|
||||
close (uc->fd);
|
||||
uc->fd = -1;
|
||||
if (NULL != uc->filename)
|
||||
{
|
||||
unlink (uc->filename);
|
||||
free (uc->filename);
|
||||
uc->filename = NULL;
|
||||
}
|
||||
return MHD_NO;
|
||||
}
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
@@ -625,32 +628,32 @@ process_upload_data (void *cls,
|
||||
*/
|
||||
static void
|
||||
response_completed_callback (void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
void **con_cls,
|
||||
enum MHD_RequestTerminationCode toe)
|
||||
struct MHD_Connection *connection,
|
||||
void **con_cls,
|
||||
enum MHD_RequestTerminationCode toe)
|
||||
{
|
||||
struct UploadContext *uc = *con_cls;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)connection; /* Unused. Silent compiler warning. */
|
||||
(void)toe; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) connection; /* Unused. Silent compiler warning. */
|
||||
(void) toe; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (NULL == uc)
|
||||
return; /* this request wasn't an upload request */
|
||||
if (NULL != uc->pp)
|
||||
{
|
||||
MHD_destroy_post_processor (uc->pp);
|
||||
uc->pp = NULL;
|
||||
}
|
||||
{
|
||||
MHD_destroy_post_processor (uc->pp);
|
||||
uc->pp = NULL;
|
||||
}
|
||||
if (-1 != uc->fd)
|
||||
{
|
||||
(void) close (uc->fd);
|
||||
if (NULL != uc->filename)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Upload of file `%s' failed (incomplete or aborted), removing file.\n",
|
||||
uc->filename);
|
||||
(void) unlink (uc->filename);
|
||||
}
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Upload of file `%s' failed (incomplete or aborted), removing file.\n",
|
||||
uc->filename);
|
||||
(void) unlink (uc->filename);
|
||||
}
|
||||
}
|
||||
if (NULL != uc->filename)
|
||||
free (uc->filename);
|
||||
@@ -672,12 +675,12 @@ return_directory_response (struct MHD_Connection *connection)
|
||||
(void) pthread_mutex_lock (&mutex);
|
||||
if (NULL == cached_directory_response)
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
internal_error_response);
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
internal_error_response);
|
||||
else
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_OK,
|
||||
cached_directory_response);
|
||||
MHD_HTTP_OK,
|
||||
cached_directory_response);
|
||||
(void) pthread_mutex_unlock (&mutex);
|
||||
return ret;
|
||||
}
|
||||
@@ -698,131 +701,131 @@ return_directory_response (struct MHD_Connection *connection)
|
||||
*/
|
||||
static int
|
||||
generate_page (void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
const char *url,
|
||||
const char *method,
|
||||
const char *version,
|
||||
const char *upload_data,
|
||||
size_t *upload_data_size, void **ptr)
|
||||
struct MHD_Connection *connection,
|
||||
const char *url,
|
||||
const char *method,
|
||||
const char *version,
|
||||
const char *upload_data,
|
||||
size_t *upload_data_size, void **ptr)
|
||||
{
|
||||
struct MHD_Response *response;
|
||||
int ret;
|
||||
int fd;
|
||||
struct stat buf;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 != strcmp (url, "/"))
|
||||
{
|
||||
/* should be file download */
|
||||
#ifdef MHD_HAVE_LIBMAGIC
|
||||
char file_data[MAGIC_HEADER_SIZE];
|
||||
ssize_t got;
|
||||
#endif /* MHD_HAVE_LIBMAGIC */
|
||||
const char *mime;
|
||||
|
||||
if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
|
||||
return MHD_NO; /* unexpected method (we're not polite...) */
|
||||
fd = -1;
|
||||
if ( (NULL == strstr (&url[1], "..")) &&
|
||||
('/' != url[1]) )
|
||||
{
|
||||
/* should be file download */
|
||||
#ifdef MHD_HAVE_LIBMAGIC
|
||||
char file_data[MAGIC_HEADER_SIZE];
|
||||
ssize_t got;
|
||||
#endif /* MHD_HAVE_LIBMAGIC */
|
||||
const char *mime;
|
||||
|
||||
if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
|
||||
return MHD_NO; /* unexpected method (we're not polite...) */
|
||||
fd = -1;
|
||||
if ( (NULL == strstr (&url[1], "..")) &&
|
||||
('/' != url[1]) )
|
||||
{
|
||||
fd = open (&url[1], O_RDONLY);
|
||||
if ( (-1 != fd) &&
|
||||
( (0 != fstat (fd, &buf)) ||
|
||||
(! S_ISREG (buf.st_mode)) ) )
|
||||
{
|
||||
(void) close (fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
if (-1 == fd)
|
||||
return MHD_queue_response (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
file_not_found_response);
|
||||
#ifdef MHD_HAVE_LIBMAGIC
|
||||
/* read beginning of the file to determine mime type */
|
||||
got = read (fd, file_data, sizeof (file_data));
|
||||
(void) lseek (fd, 0, SEEK_SET);
|
||||
if (-1 != got)
|
||||
mime = magic_buffer (magic, file_data, got);
|
||||
else
|
||||
#endif /* MHD_HAVE_LIBMAGIC */
|
||||
mime = NULL;
|
||||
|
||||
if (NULL == (response = MHD_create_response_from_fd (buf.st_size,
|
||||
fd)))
|
||||
{
|
||||
/* internal error (i.e. out of memory) */
|
||||
(void) close (fd);
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
/* add mime type if we had one */
|
||||
if (NULL != mime)
|
||||
(void) MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_TYPE,
|
||||
mime);
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_OK,
|
||||
response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
fd = open (&url[1], O_RDONLY);
|
||||
if ( (-1 != fd) &&
|
||||
( (0 != fstat (fd, &buf)) ||
|
||||
(! S_ISREG (buf.st_mode)) ) )
|
||||
{
|
||||
(void) close (fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
if (-1 == fd)
|
||||
return MHD_queue_response (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
file_not_found_response);
|
||||
#ifdef MHD_HAVE_LIBMAGIC
|
||||
/* read beginning of the file to determine mime type */
|
||||
got = read (fd, file_data, sizeof (file_data));
|
||||
(void) lseek (fd, 0, SEEK_SET);
|
||||
if (-1 != got)
|
||||
mime = magic_buffer (magic, file_data, got);
|
||||
else
|
||||
#endif /* MHD_HAVE_LIBMAGIC */
|
||||
mime = NULL;
|
||||
|
||||
if (NULL == (response = MHD_create_response_from_fd (buf.st_size,
|
||||
fd)))
|
||||
{
|
||||
/* internal error (i.e. out of memory) */
|
||||
(void) close (fd);
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
/* add mime type if we had one */
|
||||
if (NULL != mime)
|
||||
(void) MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_TYPE,
|
||||
mime);
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_OK,
|
||||
response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
|
||||
{
|
||||
/* upload! */
|
||||
struct UploadContext *uc = *ptr;
|
||||
{
|
||||
/* upload! */
|
||||
struct UploadContext *uc = *ptr;
|
||||
|
||||
if (NULL == uc)
|
||||
{
|
||||
if (NULL == (uc = malloc (sizeof (struct UploadContext))))
|
||||
return MHD_NO; /* out of memory, close connection */
|
||||
memset (uc, 0, sizeof (struct UploadContext));
|
||||
uc->fd = -1;
|
||||
uc->connection = connection;
|
||||
uc->pp = MHD_create_post_processor (connection,
|
||||
64 * 1024 /* buffer size */,
|
||||
&process_upload_data, uc);
|
||||
if (NULL == uc->pp)
|
||||
{
|
||||
/* out of memory, close connection */
|
||||
free (uc);
|
||||
return MHD_NO;
|
||||
}
|
||||
*ptr = uc;
|
||||
return MHD_YES;
|
||||
}
|
||||
if (0 != *upload_data_size)
|
||||
{
|
||||
if (NULL == uc->response)
|
||||
(void) MHD_post_process (uc->pp,
|
||||
upload_data,
|
||||
*upload_data_size);
|
||||
*upload_data_size = 0;
|
||||
return MHD_YES;
|
||||
}
|
||||
/* end of upload, finish it! */
|
||||
MHD_destroy_post_processor (uc->pp);
|
||||
uc->pp = NULL;
|
||||
if (-1 != uc->fd)
|
||||
{
|
||||
close (uc->fd);
|
||||
uc->fd = -1;
|
||||
}
|
||||
if (NULL != uc->response)
|
||||
{
|
||||
return MHD_queue_response (connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
uc->response);
|
||||
}
|
||||
else
|
||||
{
|
||||
update_directory ();
|
||||
return return_directory_response (connection);
|
||||
}
|
||||
if (NULL == uc)
|
||||
{
|
||||
if (NULL == (uc = malloc (sizeof (struct UploadContext))))
|
||||
return MHD_NO; /* out of memory, close connection */
|
||||
memset (uc, 0, sizeof (struct UploadContext));
|
||||
uc->fd = -1;
|
||||
uc->connection = connection;
|
||||
uc->pp = MHD_create_post_processor (connection,
|
||||
64 * 1024 /* buffer size */,
|
||||
&process_upload_data, uc);
|
||||
if (NULL == uc->pp)
|
||||
{
|
||||
/* out of memory, close connection */
|
||||
free (uc);
|
||||
return MHD_NO;
|
||||
}
|
||||
*ptr = uc;
|
||||
return MHD_YES;
|
||||
}
|
||||
if (0 != *upload_data_size)
|
||||
{
|
||||
if (NULL == uc->response)
|
||||
(void) MHD_post_process (uc->pp,
|
||||
upload_data,
|
||||
*upload_data_size);
|
||||
*upload_data_size = 0;
|
||||
return MHD_YES;
|
||||
}
|
||||
/* end of upload, finish it! */
|
||||
MHD_destroy_post_processor (uc->pp);
|
||||
uc->pp = NULL;
|
||||
if (-1 != uc->fd)
|
||||
{
|
||||
close (uc->fd);
|
||||
uc->fd = -1;
|
||||
}
|
||||
if (NULL != uc->response)
|
||||
{
|
||||
return MHD_queue_response (connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
uc->response);
|
||||
}
|
||||
else
|
||||
{
|
||||
update_directory ();
|
||||
return return_directory_response (connection);
|
||||
}
|
||||
}
|
||||
if (0 == strcmp (method, MHD_HTTP_METHOD_GET))
|
||||
{
|
||||
return return_directory_response (connection);
|
||||
@@ -830,8 +833,8 @@ generate_page (void *cls,
|
||||
|
||||
/* unexpected request, refuse */
|
||||
return MHD_queue_response (connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
request_refused_response);
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
request_refused_response);
|
||||
}
|
||||
|
||||
|
||||
@@ -844,7 +847,7 @@ generate_page (void *cls,
|
||||
static void
|
||||
catcher (int sig)
|
||||
{
|
||||
(void)sig; /* Unused. Silent compiler warning. */
|
||||
(void) sig; /* Unused. Silent compiler warning. */
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
@@ -873,53 +876,53 @@ ignore_sigpipe (void)
|
||||
|
||||
/* test server key */
|
||||
const char srv_signed_key_pem[] = "-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
"MIIEowIBAAKCAQEAvfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW\n"
|
||||
"+K03KwEku55QvnUndwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8IL\n"
|
||||
"q4sw32vo0fbMu5BZF49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ0\n"
|
||||
"20Q5EAAEseD1YtWCIpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6\n"
|
||||
"QYGGh1QmHRPAy3CBII6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6x\n"
|
||||
"yoOl204xuekZOaG9RUPId74Rtmwfi1TLbBzo2wIDAQABAoIBADu09WSICNq5cMe4\n"
|
||||
"+NKCLlgAT1NiQpLls1gKRbDhKiHU9j8QWNvWWkJWrCya4QdUfLCfeddCMeiQmv3K\n"
|
||||
"lJMvDs+5OjJSHFoOsGiuW2Ias7IjnIojaJalfBml6frhJ84G27IXmdz6gzOiTIer\n"
|
||||
"DjeAgcwBaKH5WwIay2TxIaScl7AwHBauQkrLcyb4hTmZuQh6ArVIN6+pzoVuORXM\n"
|
||||
"bpeNWl2l/HSN3VtUN6aCAKbN/X3o0GavCCMn5Fa85uJFsab4ss/uP+2PusU71+zP\n"
|
||||
"sBm6p/2IbGvF5k3VPDA7X5YX61sukRjRBihY8xSnNYx1UcoOsX6AiPnbhifD8+xQ\n"
|
||||
"Tlf8oJUCgYEA0BTfzqNpr9Wxw5/QXaSdw7S/0eP5a0C/nwURvmfSzuTD4equzbEN\n"
|
||||
"d+dI/s2JMxrdj/I4uoAfUXRGaabevQIjFzC9uyE3LaOyR2zhuvAzX+vVcs6bSXeU\n"
|
||||
"pKpCAcN+3Z3evMaX2f+z/nfSUAl2i4J2R+/LQAWJW4KwRky/m+cxpfUCgYEA6bN1\n"
|
||||
"b73bMgM8wpNt6+fcmS+5n0iZihygQ2U2DEud8nZJL4Nrm1dwTnfZfJBnkGj6+0Q0\n"
|
||||
"cOwj2KS0/wcEdJBP0jucU4v60VMhp75AQeHqidIde0bTViSRo3HWKXHBIFGYoU3T\n"
|
||||
"LyPyKndbqsOObnsFXHn56Nwhr2HLf6nw4taGQY8CgYBoSW36FLCNbd6QGvLFXBGt\n"
|
||||
"2lMhEM8az/K58kJ4WXSwOLtr6MD/WjNT2tkcy0puEJLm6BFCd6A6pLn9jaKou/92\n"
|
||||
"SfltZjJPb3GUlp9zn5tAAeSSi7YMViBrfuFiHObij5LorefBXISLjuYbMwL03MgH\n"
|
||||
"Ocl2JtA2ywMp2KFXs8GQWQKBgFyIVv5ogQrbZ0pvj31xr9HjqK6d01VxIi+tOmpB\n"
|
||||
"4ocnOLEcaxX12BzprW55ytfOCVpF1jHD/imAhb3YrHXu0fwe6DXYXfZV4SSG2vB7\n"
|
||||
"IB9z14KBN5qLHjNGFpMQXHSMek+b/ftTU0ZnPh9uEM5D3YqRLVd7GcdUhHvG8P8Q\n"
|
||||
"C9aXAoGBAJtID6h8wOGMP0XYX5YYnhlC7dOLfk8UYrzlp3xhqVkzKthTQTj6wx9R\n"
|
||||
"GtC4k7U1ki8oJsfcIlBNXd768fqDVWjYju5rzShMpo8OCTS6ipAblKjCxPPVhIpv\n"
|
||||
"tWPlbSn1qj6wylstJ5/3Z+ZW5H4wIKp5jmLiioDhcP0L/Ex3Zx8O\n"
|
||||
"-----END RSA PRIVATE KEY-----\n";
|
||||
"MIIEowIBAAKCAQEAvfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW\n"
|
||||
"+K03KwEku55QvnUndwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8IL\n"
|
||||
"q4sw32vo0fbMu5BZF49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ0\n"
|
||||
"20Q5EAAEseD1YtWCIpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6\n"
|
||||
"QYGGh1QmHRPAy3CBII6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6x\n"
|
||||
"yoOl204xuekZOaG9RUPId74Rtmwfi1TLbBzo2wIDAQABAoIBADu09WSICNq5cMe4\n"
|
||||
"+NKCLlgAT1NiQpLls1gKRbDhKiHU9j8QWNvWWkJWrCya4QdUfLCfeddCMeiQmv3K\n"
|
||||
"lJMvDs+5OjJSHFoOsGiuW2Ias7IjnIojaJalfBml6frhJ84G27IXmdz6gzOiTIer\n"
|
||||
"DjeAgcwBaKH5WwIay2TxIaScl7AwHBauQkrLcyb4hTmZuQh6ArVIN6+pzoVuORXM\n"
|
||||
"bpeNWl2l/HSN3VtUN6aCAKbN/X3o0GavCCMn5Fa85uJFsab4ss/uP+2PusU71+zP\n"
|
||||
"sBm6p/2IbGvF5k3VPDA7X5YX61sukRjRBihY8xSnNYx1UcoOsX6AiPnbhifD8+xQ\n"
|
||||
"Tlf8oJUCgYEA0BTfzqNpr9Wxw5/QXaSdw7S/0eP5a0C/nwURvmfSzuTD4equzbEN\n"
|
||||
"d+dI/s2JMxrdj/I4uoAfUXRGaabevQIjFzC9uyE3LaOyR2zhuvAzX+vVcs6bSXeU\n"
|
||||
"pKpCAcN+3Z3evMaX2f+z/nfSUAl2i4J2R+/LQAWJW4KwRky/m+cxpfUCgYEA6bN1\n"
|
||||
"b73bMgM8wpNt6+fcmS+5n0iZihygQ2U2DEud8nZJL4Nrm1dwTnfZfJBnkGj6+0Q0\n"
|
||||
"cOwj2KS0/wcEdJBP0jucU4v60VMhp75AQeHqidIde0bTViSRo3HWKXHBIFGYoU3T\n"
|
||||
"LyPyKndbqsOObnsFXHn56Nwhr2HLf6nw4taGQY8CgYBoSW36FLCNbd6QGvLFXBGt\n"
|
||||
"2lMhEM8az/K58kJ4WXSwOLtr6MD/WjNT2tkcy0puEJLm6BFCd6A6pLn9jaKou/92\n"
|
||||
"SfltZjJPb3GUlp9zn5tAAeSSi7YMViBrfuFiHObij5LorefBXISLjuYbMwL03MgH\n"
|
||||
"Ocl2JtA2ywMp2KFXs8GQWQKBgFyIVv5ogQrbZ0pvj31xr9HjqK6d01VxIi+tOmpB\n"
|
||||
"4ocnOLEcaxX12BzprW55ytfOCVpF1jHD/imAhb3YrHXu0fwe6DXYXfZV4SSG2vB7\n"
|
||||
"IB9z14KBN5qLHjNGFpMQXHSMek+b/ftTU0ZnPh9uEM5D3YqRLVd7GcdUhHvG8P8Q\n"
|
||||
"C9aXAoGBAJtID6h8wOGMP0XYX5YYnhlC7dOLfk8UYrzlp3xhqVkzKthTQTj6wx9R\n"
|
||||
"GtC4k7U1ki8oJsfcIlBNXd768fqDVWjYju5rzShMpo8OCTS6ipAblKjCxPPVhIpv\n"
|
||||
"tWPlbSn1qj6wylstJ5/3Z+ZW5H4wIKp5jmLiioDhcP0L/Ex3Zx8O\n"
|
||||
"-----END RSA PRIVATE KEY-----\n";
|
||||
|
||||
/* test server CA signed certificates */
|
||||
const char srv_signed_cert_pem[] = "-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDGzCCAgWgAwIBAgIES0KCvTALBgkqhkiG9w0BAQUwFzEVMBMGA1UEAxMMdGVz\n"
|
||||
"dF9jYV9jZXJ0MB4XDTEwMDEwNTAwMDcyNVoXDTQ1MDMxMjAwMDcyNVowFzEVMBMG\n"
|
||||
"A1UEAxMMdGVzdF9jYV9jZXJ0MIIBHzALBgkqhkiG9w0BAQEDggEOADCCAQkCggEA\n"
|
||||
"vfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW+K03KwEku55QvnUn\n"
|
||||
"dwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8ILq4sw32vo0fbMu5BZ\n"
|
||||
"F49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ020Q5EAAEseD1YtWC\n"
|
||||
"IpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6QYGGh1QmHRPAy3CB\n"
|
||||
"II6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6xyoOl204xuekZOaG9\n"
|
||||
"RUPId74Rtmwfi1TLbBzo2wIDAQABo3YwdDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQM\n"
|
||||
"MAoGCCsGAQUFBwMBMA8GA1UdDwEB/wQFAwMHIAAwHQYDVR0OBBYEFOFi4ilKOP1d\n"
|
||||
"XHlWCMwmVKr7mgy8MB8GA1UdIwQYMBaAFP2olB4s2T/xuoQ5pT2RKojFwZo2MAsG\n"
|
||||
"CSqGSIb3DQEBBQOCAQEAHVWPxazupbOkG7Did+dY9z2z6RjTzYvurTtEKQgzM2Vz\n"
|
||||
"GQBA+3pZ3c5mS97fPIs9hZXfnQeelMeZ2XP1a+9vp35bJjZBBhVH+pqxjCgiUflg\n"
|
||||
"A3Zqy0XwwVCgQLE2HyaU3DLUD/aeIFK5gJaOSdNTXZLv43K8kl4cqDbMeRpVTbkt\n"
|
||||
"YmG4AyEOYRNKGTqMEJXJoxD5E3rBUNrVI/XyTjYrulxbNPcMWEHKNeeqWpKDYTFo\n"
|
||||
"Bb01PCthGXiq/4A2RLAFosadzRa8SBpoSjPPfZ0b2w4MJpReHqKbR5+T2t6hzml6\n"
|
||||
"4ToyOKPDmamiTuN5KzLN3cw7DQlvWMvqSOChPLnA3Q==\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
"MIIDGzCCAgWgAwIBAgIES0KCvTALBgkqhkiG9w0BAQUwFzEVMBMGA1UEAxMMdGVz\n"
|
||||
"dF9jYV9jZXJ0MB4XDTEwMDEwNTAwMDcyNVoXDTQ1MDMxMjAwMDcyNVowFzEVMBMG\n"
|
||||
"A1UEAxMMdGVzdF9jYV9jZXJ0MIIBHzALBgkqhkiG9w0BAQEDggEOADCCAQkCggEA\n"
|
||||
"vfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW+K03KwEku55QvnUn\n"
|
||||
"dwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8ILq4sw32vo0fbMu5BZ\n"
|
||||
"F49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ020Q5EAAEseD1YtWC\n"
|
||||
"IpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6QYGGh1QmHRPAy3CB\n"
|
||||
"II6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6xyoOl204xuekZOaG9\n"
|
||||
"RUPId74Rtmwfi1TLbBzo2wIDAQABo3YwdDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQM\n"
|
||||
"MAoGCCsGAQUFBwMBMA8GA1UdDwEB/wQFAwMHIAAwHQYDVR0OBBYEFOFi4ilKOP1d\n"
|
||||
"XHlWCMwmVKr7mgy8MB8GA1UdIwQYMBaAFP2olB4s2T/xuoQ5pT2RKojFwZo2MAsG\n"
|
||||
"CSqGSIb3DQEBBQOCAQEAHVWPxazupbOkG7Did+dY9z2z6RjTzYvurTtEKQgzM2Vz\n"
|
||||
"GQBA+3pZ3c5mS97fPIs9hZXfnQeelMeZ2XP1a+9vp35bJjZBBhVH+pqxjCgiUflg\n"
|
||||
"A3Zqy0XwwVCgQLE2HyaU3DLUD/aeIFK5gJaOSdNTXZLv43K8kl4cqDbMeRpVTbkt\n"
|
||||
"YmG4AyEOYRNKGTqMEJXJoxD5E3rBUNrVI/XyTjYrulxbNPcMWEHKNeeqWpKDYTFo\n"
|
||||
"Bb01PCthGXiq/4A2RLAFosadzRa8SBpoSjPPfZ0b2w4MJpReHqKbR5+T2t6hzml6\n"
|
||||
"4ToyOKPDmamiTuN5KzLN3cw7DQlvWMvqSOChPLnA3Q==\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
|
||||
/**
|
||||
@@ -940,11 +943,11 @@ main (int argc, char *const *argv)
|
||||
if ( (argc != 2) ||
|
||||
(1 != sscanf (argv[1], "%u", &port)) ||
|
||||
(UINT16_MAX < port) )
|
||||
{
|
||||
fprintf (stderr,
|
||||
"%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
fprintf (stderr,
|
||||
"%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
#ifndef MINGW
|
||||
ignore_sigpipe ();
|
||||
#endif
|
||||
@@ -954,35 +957,46 @@ main (int argc, char *const *argv)
|
||||
#endif /* MHD_HAVE_LIBMAGIC */
|
||||
|
||||
(void) pthread_mutex_init (&mutex, NULL);
|
||||
file_not_found_response = MHD_create_response_from_buffer (strlen (FILE_NOT_FOUND_PAGE),
|
||||
(void *) FILE_NOT_FOUND_PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
file_not_found_response = MHD_create_response_from_buffer (strlen (
|
||||
FILE_NOT_FOUND_PAGE),
|
||||
(void *)
|
||||
FILE_NOT_FOUND_PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
mark_as_html (file_not_found_response);
|
||||
request_refused_response = MHD_create_response_from_buffer (strlen (REQUEST_REFUSED_PAGE),
|
||||
(void *) REQUEST_REFUSED_PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
request_refused_response = MHD_create_response_from_buffer (strlen (
|
||||
REQUEST_REFUSED_PAGE),
|
||||
(void *)
|
||||
REQUEST_REFUSED_PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
mark_as_html (request_refused_response);
|
||||
internal_error_response = MHD_create_response_from_buffer (strlen (INTERNAL_ERROR_PAGE),
|
||||
(void *) INTERNAL_ERROR_PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
internal_error_response = MHD_create_response_from_buffer (strlen (
|
||||
INTERNAL_ERROR_PAGE),
|
||||
(void *)
|
||||
INTERNAL_ERROR_PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
mark_as_html (internal_error_response);
|
||||
update_directory ();
|
||||
d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_TLS,
|
||||
d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD
|
||||
| MHD_USE_ERROR_LOG | MHD_USE_TLS,
|
||||
port,
|
||||
NULL, NULL,
|
||||
&generate_page, NULL,
|
||||
MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (256 * 1024),
|
||||
&generate_page, NULL,
|
||||
MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (256
|
||||
* 1024),
|
||||
#if PRODUCTION
|
||||
MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) (64),
|
||||
MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) (64),
|
||||
#endif
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) (120 /* seconds */),
|
||||
MHD_OPTION_THREAD_POOL_SIZE, (unsigned int) NUMBER_OF_THREADS,
|
||||
MHD_OPTION_NOTIFY_COMPLETED, &response_completed_callback, NULL,
|
||||
/* Optionally, the gnutls_load_file() can be used to
|
||||
load the key and the certificate from file. */
|
||||
MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem,
|
||||
MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem,
|
||||
MHD_OPTION_END);
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned
|
||||
int) (120 /* seconds */),
|
||||
MHD_OPTION_THREAD_POOL_SIZE, (unsigned
|
||||
int) NUMBER_OF_THREADS,
|
||||
MHD_OPTION_NOTIFY_COMPLETED,
|
||||
&response_completed_callback, NULL,
|
||||
/* Optionally, the gnutls_load_file() can be used to
|
||||
load the key and the certificate from file. */
|
||||
MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem,
|
||||
MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem,
|
||||
MHD_OPTION_END);
|
||||
if (NULL == d)
|
||||
return 1;
|
||||
fprintf (stderr, "HTTP server running. Press ENTER to stop the server\n");
|
||||
|
||||
@@ -26,9 +26,11 @@
|
||||
#include <microhttpd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>Access granted</body></html>"
|
||||
#define PAGE \
|
||||
"<html><head><title>libmicrohttpd demo</title></head><body>Access granted</body></html>"
|
||||
|
||||
#define DENIED "<html><head><title>libmicrohttpd demo</title></head><body>Access denied</body></html>"
|
||||
#define DENIED \
|
||||
"<html><head><title>libmicrohttpd demo</title></head><body>Access denied</body></html>"
|
||||
|
||||
#define MY_OPAQUE_STR "11733b200778ce33060f31c9af70a870ba96ddd4"
|
||||
|
||||
@@ -45,51 +47,52 @@ ahc_echo (void *cls,
|
||||
const char *password = "testpass";
|
||||
const char *realm = "test@example.com";
|
||||
int ret;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)url; /* Unused. Silent compiler warning. */
|
||||
(void)method; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void)ptr; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) url; /* Unused. Silent compiler warning. */
|
||||
(void) method; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) ptr; /* Unused. Silent compiler warning. */
|
||||
|
||||
username = MHD_digest_auth_get_username(connection);
|
||||
username = MHD_digest_auth_get_username (connection);
|
||||
if (NULL == username)
|
||||
{
|
||||
response = MHD_create_response_from_buffer(strlen (DENIED),
|
||||
DENIED,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_auth_fail_response(connection, realm,
|
||||
MY_OPAQUE_STR,
|
||||
response,
|
||||
MHD_NO);
|
||||
MHD_destroy_response(response);
|
||||
return ret;
|
||||
}
|
||||
ret = MHD_digest_auth_check(connection, realm,
|
||||
username,
|
||||
password,
|
||||
300);
|
||||
{
|
||||
response = MHD_create_response_from_buffer (strlen (DENIED),
|
||||
DENIED,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_auth_fail_response (connection, realm,
|
||||
MY_OPAQUE_STR,
|
||||
response,
|
||||
MHD_NO);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
}
|
||||
ret = MHD_digest_auth_check (connection, realm,
|
||||
username,
|
||||
password,
|
||||
300);
|
||||
MHD_free (username);
|
||||
if ( (ret == MHD_INVALID_NONCE) ||
|
||||
(ret == MHD_NO) )
|
||||
{
|
||||
response = MHD_create_response_from_buffer(strlen (DENIED),
|
||||
DENIED,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
if (NULL == response)
|
||||
return MHD_NO;
|
||||
ret = MHD_queue_auth_fail_response(connection, realm,
|
||||
MY_OPAQUE_STR,
|
||||
response,
|
||||
(ret == MHD_INVALID_NONCE) ? MHD_YES : MHD_NO);
|
||||
MHD_destroy_response(response);
|
||||
return ret;
|
||||
}
|
||||
response = MHD_create_response_from_buffer(strlen(PAGE), PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response(response);
|
||||
{
|
||||
response = MHD_create_response_from_buffer (strlen (DENIED),
|
||||
DENIED,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
if (NULL == response)
|
||||
return MHD_NO;
|
||||
ret = MHD_queue_auth_fail_response (connection, realm,
|
||||
MY_OPAQUE_STR,
|
||||
response,
|
||||
(ret == MHD_INVALID_NONCE) ? MHD_YES :
|
||||
MHD_NO);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
}
|
||||
response = MHD_create_response_from_buffer (strlen (PAGE), PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -104,40 +107,41 @@ main (int argc, char *const *argv)
|
||||
struct MHD_Daemon *d;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
fd = open("/dev/urandom", O_RDONLY);
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
fd = open ("/dev/urandom", O_RDONLY);
|
||||
if (-1 == fd)
|
||||
{
|
||||
fprintf (stderr, "Failed to open `%s': %s\n",
|
||||
"/dev/urandom",
|
||||
strerror (errno));
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
fprintf (stderr, "Failed to open `%s': %s\n",
|
||||
"/dev/urandom",
|
||||
strerror (errno));
|
||||
return 1;
|
||||
}
|
||||
off = 0;
|
||||
while (off < 8)
|
||||
{
|
||||
len = read (fd, rnd, 8);
|
||||
if (len == -1)
|
||||
{
|
||||
len = read(fd, rnd, 8);
|
||||
if (len == -1)
|
||||
{
|
||||
fprintf (stderr, "Failed to read `%s': %s\n",
|
||||
"/dev/urandom",
|
||||
strerror (errno));
|
||||
(void) close (fd);
|
||||
return 1;
|
||||
}
|
||||
off += len;
|
||||
fprintf (stderr, "Failed to read `%s': %s\n",
|
||||
"/dev/urandom",
|
||||
strerror (errno));
|
||||
(void) close (fd);
|
||||
return 1;
|
||||
}
|
||||
(void) close(fd);
|
||||
d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
off += len;
|
||||
}
|
||||
(void) close (fd);
|
||||
d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION
|
||||
| MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
atoi (argv[1]),
|
||||
NULL, NULL, &ahc_echo, PAGE,
|
||||
MHD_OPTION_DIGEST_AUTH_RANDOM, sizeof(rnd), rnd,
|
||||
MHD_OPTION_NONCE_NC_SIZE, 300,
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120,
|
||||
MHD_OPTION_END);
|
||||
MHD_OPTION_DIGEST_AUTH_RANDOM, sizeof(rnd), rnd,
|
||||
MHD_OPTION_NONCE_NC_SIZE, 300,
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120,
|
||||
MHD_OPTION_END);
|
||||
if (d == NULL)
|
||||
return 1;
|
||||
(void) getc (stdin);
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
#include "platform.h"
|
||||
#include <microhttpd.h>
|
||||
|
||||
#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
|
||||
#define PAGE \
|
||||
"<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
|
||||
|
||||
static int
|
||||
ahc_echo (void *cls,
|
||||
@@ -39,23 +40,23 @@ ahc_echo (void *cls,
|
||||
const char *me = cls;
|
||||
struct MHD_Response *response;
|
||||
int ret;
|
||||
(void)url; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) url; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 != strcmp (method, "GET"))
|
||||
return MHD_NO; /* unexpected method */
|
||||
if (&aptr != *ptr)
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
*ptr = NULL; /* reset when done */
|
||||
response = MHD_create_response_from_buffer (strlen (me),
|
||||
(void *) me,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
(void *) me,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
@@ -68,15 +69,16 @@ main (int argc, char *const *argv)
|
||||
struct MHD_Daemon *d;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_DUAL_STACK,
|
||||
atoi (argv[1]),
|
||||
NULL, NULL, &ahc_echo, PAGE,
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120,
|
||||
MHD_OPTION_END);
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG
|
||||
| MHD_USE_DUAL_STACK,
|
||||
atoi (argv[1]),
|
||||
NULL, NULL, &ahc_echo, PAGE,
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120,
|
||||
MHD_OPTION_END);
|
||||
(void) getc (stdin);
|
||||
MHD_stop_daemon (d);
|
||||
return 0;
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
#include <microhttpd.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"
|
||||
#define PAGE \
|
||||
"<html><head><title>File not found</title></head><body>File not found</body></html>"
|
||||
|
||||
|
||||
static ssize_t
|
||||
@@ -66,17 +67,17 @@ dir_reader (void *cls, uint64_t pos, char *buf, size_t max)
|
||||
|
||||
if (max < 512)
|
||||
return 0;
|
||||
(void)pos; /* 'pos' is ignored as function return next one single entry per call. */
|
||||
(void) pos; /* 'pos' is ignored as function return next one single entry per call. */
|
||||
do
|
||||
{
|
||||
e = readdir (dir);
|
||||
if (e == NULL)
|
||||
return MHD_CONTENT_READER_END_OF_STREAM;
|
||||
{
|
||||
e = readdir (dir);
|
||||
if (e == NULL)
|
||||
return MHD_CONTENT_READER_END_OF_STREAM;
|
||||
} while (e->d_name[0] == '.');
|
||||
return snprintf (buf, max,
|
||||
"<a href=\"/%s\">%s</a><br>",
|
||||
e->d_name,
|
||||
e->d_name);
|
||||
"<a href=\"/%s\">%s</a><br>",
|
||||
e->d_name,
|
||||
e->d_name);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +88,7 @@ ahc_echo (void *cls,
|
||||
const char *method,
|
||||
const char *version,
|
||||
const char *upload_data,
|
||||
size_t *upload_data_size, void **ptr)
|
||||
size_t *upload_data_size, void **ptr)
|
||||
{
|
||||
static int aptr;
|
||||
struct MHD_Response *response;
|
||||
@@ -97,90 +98,90 @@ ahc_echo (void *cls,
|
||||
DIR *dir;
|
||||
struct stat buf;
|
||||
char emsg[1024];
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
|
||||
return MHD_NO; /* unexpected method */
|
||||
if (&aptr != *ptr)
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
*ptr = NULL; /* reset when done */
|
||||
|
||||
file = fopen (&url[1], "rb");
|
||||
if (NULL != file)
|
||||
{
|
||||
fd = fileno (file);
|
||||
if (-1 == fd)
|
||||
{
|
||||
fd = fileno (file);
|
||||
if (-1 == fd)
|
||||
{
|
||||
(void) fclose (file);
|
||||
return MHD_NO; /* internal error */
|
||||
}
|
||||
if ( (0 != fstat (fd, &buf)) ||
|
||||
(! S_ISREG (buf.st_mode)) )
|
||||
{
|
||||
/* not a regular file, refuse to serve */
|
||||
fclose (file);
|
||||
file = NULL;
|
||||
}
|
||||
(void) fclose (file);
|
||||
return MHD_NO; /* internal error */
|
||||
}
|
||||
if ( (0 != fstat (fd, &buf)) ||
|
||||
(! S_ISREG (buf.st_mode)) )
|
||||
{
|
||||
/* not a regular file, refuse to serve */
|
||||
fclose (file);
|
||||
file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == file)
|
||||
{
|
||||
dir = opendir (".");
|
||||
if (NULL == dir)
|
||||
{
|
||||
dir = opendir (".");
|
||||
if (NULL == dir)
|
||||
{
|
||||
/* most likely cause: more concurrent requests than
|
||||
available file descriptors / 2 */
|
||||
snprintf (emsg,
|
||||
sizeof (emsg),
|
||||
"Failed to open directory `.': %s\n",
|
||||
strerror (errno));
|
||||
response = MHD_create_response_from_buffer (strlen (emsg),
|
||||
emsg,
|
||||
MHD_RESPMEM_MUST_COPY);
|
||||
if (NULL == response)
|
||||
return MHD_NO;
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_SERVICE_UNAVAILABLE,
|
||||
response);
|
||||
MHD_destroy_response (response);
|
||||
}
|
||||
else
|
||||
{
|
||||
response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
|
||||
32 * 1024,
|
||||
&dir_reader,
|
||||
dir,
|
||||
&dir_free_callback);
|
||||
if (NULL == response)
|
||||
{
|
||||
closedir (dir);
|
||||
return MHD_NO;
|
||||
}
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response (response);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k page size */
|
||||
&file_reader,
|
||||
file,
|
||||
&file_free_callback);
|
||||
/* most likely cause: more concurrent requests than
|
||||
available file descriptors / 2 */
|
||||
snprintf (emsg,
|
||||
sizeof (emsg),
|
||||
"Failed to open directory `.': %s\n",
|
||||
strerror (errno));
|
||||
response = MHD_create_response_from_buffer (strlen (emsg),
|
||||
emsg,
|
||||
MHD_RESPMEM_MUST_COPY);
|
||||
if (NULL == response)
|
||||
{
|
||||
fclose (file);
|
||||
return MHD_NO;
|
||||
}
|
||||
return MHD_NO;
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_SERVICE_UNAVAILABLE,
|
||||
response);
|
||||
MHD_destroy_response (response);
|
||||
}
|
||||
else
|
||||
{
|
||||
response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
|
||||
32 * 1024,
|
||||
&dir_reader,
|
||||
dir,
|
||||
&dir_free_callback);
|
||||
if (NULL == response)
|
||||
{
|
||||
closedir (dir);
|
||||
return MHD_NO;
|
||||
}
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response (response);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k page size */
|
||||
&file_reader,
|
||||
file,
|
||||
&file_free_callback);
|
||||
if (NULL == response)
|
||||
{
|
||||
fclose (file);
|
||||
return MHD_NO;
|
||||
}
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response (response);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -191,11 +192,12 @@ main (int argc, char *const *argv)
|
||||
struct MHD_Daemon *d;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION
|
||||
| MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
atoi (argv[1]),
|
||||
NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
|
||||
if (NULL == d)
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"
|
||||
#define PAGE \
|
||||
"<html><head><title>File not found</title></head><body>File not found</body></html>"
|
||||
|
||||
static ssize_t
|
||||
file_reader (void *cls, uint64_t pos, char *buf, size_t max)
|
||||
@@ -54,7 +55,7 @@ ahc_echo (void *cls,
|
||||
const char *method,
|
||||
const char *version,
|
||||
const char *upload_data,
|
||||
size_t *upload_data_size, void **ptr)
|
||||
size_t *upload_data_size, void **ptr)
|
||||
{
|
||||
static int aptr;
|
||||
struct MHD_Response *response;
|
||||
@@ -62,61 +63,61 @@ ahc_echo (void *cls,
|
||||
FILE *file;
|
||||
int fd;
|
||||
struct stat buf;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
|
||||
return MHD_NO; /* unexpected method */
|
||||
if (&aptr != *ptr)
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
*ptr = NULL; /* reset when done */
|
||||
|
||||
file = fopen (&url[1], "rb");
|
||||
if (NULL != file)
|
||||
{
|
||||
fd = fileno (file);
|
||||
if (-1 == fd)
|
||||
{
|
||||
fd = fileno (file);
|
||||
if (-1 == fd)
|
||||
{
|
||||
(void) fclose (file);
|
||||
return MHD_NO; /* internal error */
|
||||
}
|
||||
if ( (0 != fstat (fd, &buf)) ||
|
||||
(! S_ISREG (buf.st_mode)) )
|
||||
{
|
||||
/* not a regular file, refuse to serve */
|
||||
fclose (file);
|
||||
file = NULL;
|
||||
}
|
||||
(void) fclose (file);
|
||||
return MHD_NO; /* internal error */
|
||||
}
|
||||
if ( (0 != fstat (fd, &buf)) ||
|
||||
(! S_ISREG (buf.st_mode)) )
|
||||
{
|
||||
/* not a regular file, refuse to serve */
|
||||
fclose (file);
|
||||
file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == file)
|
||||
{
|
||||
response = MHD_create_response_from_buffer (strlen (PAGE),
|
||||
(void *) PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
|
||||
MHD_destroy_response (response);
|
||||
}
|
||||
{
|
||||
response = MHD_create_response_from_buffer (strlen (PAGE),
|
||||
(void *) PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
|
||||
MHD_destroy_response (response);
|
||||
}
|
||||
else
|
||||
{
|
||||
response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k page size */
|
||||
&file_reader,
|
||||
file,
|
||||
&free_callback);
|
||||
if (NULL == response)
|
||||
{
|
||||
response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k page size */
|
||||
&file_reader,
|
||||
file,
|
||||
&free_callback);
|
||||
if (NULL == response)
|
||||
{
|
||||
fclose (file);
|
||||
return MHD_NO;
|
||||
}
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response (response);
|
||||
fclose (file);
|
||||
return MHD_NO;
|
||||
}
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response (response);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -135,10 +136,10 @@ main (int argc, char *const *argv)
|
||||
MHD_UNSIGNED_LONG_LONG mhd_timeout;
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_ERROR_LOG,
|
||||
atoi (argv[1]),
|
||||
NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
|
||||
@@ -146,30 +147,30 @@ main (int argc, char *const *argv)
|
||||
return 1;
|
||||
end = time (NULL) + atoi (argv[2]);
|
||||
while ((t = time (NULL)) < end)
|
||||
{
|
||||
tv.tv_sec = end - t;
|
||||
tv.tv_usec = 0;
|
||||
max = 0;
|
||||
FD_ZERO (&rs);
|
||||
FD_ZERO (&ws);
|
||||
FD_ZERO (&es);
|
||||
if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
|
||||
break; /* fatal internal error */
|
||||
if (MHD_get_timeout (d, &mhd_timeout) == MHD_YES)
|
||||
{
|
||||
tv.tv_sec = end - t;
|
||||
tv.tv_usec = 0;
|
||||
max = 0;
|
||||
FD_ZERO (&rs);
|
||||
FD_ZERO (&ws);
|
||||
FD_ZERO (&es);
|
||||
if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
|
||||
break; /* fatal internal error */
|
||||
if (MHD_get_timeout (d, &mhd_timeout) == MHD_YES)
|
||||
{
|
||||
if (((MHD_UNSIGNED_LONG_LONG)tv.tv_sec) < mhd_timeout / 1000LL)
|
||||
{
|
||||
tv.tv_sec = mhd_timeout / 1000LL;
|
||||
tv.tv_usec = (mhd_timeout - (tv.tv_sec * 1000LL)) * 1000LL;
|
||||
}
|
||||
}
|
||||
if (-1 == select (max + 1, &rs, &ws, &es, &tv))
|
||||
{
|
||||
if (EINTR != errno)
|
||||
abort ();
|
||||
}
|
||||
MHD_run (d);
|
||||
if (((MHD_UNSIGNED_LONG_LONG) tv.tv_sec) < mhd_timeout / 1000LL)
|
||||
{
|
||||
tv.tv_sec = mhd_timeout / 1000LL;
|
||||
tv.tv_usec = (mhd_timeout - (tv.tv_sec * 1000LL)) * 1000LL;
|
||||
}
|
||||
}
|
||||
if (-1 == select (max + 1, &rs, &ws, &es, &tv))
|
||||
{
|
||||
if (EINTR != errno)
|
||||
abort ();
|
||||
}
|
||||
MHD_run (d);
|
||||
}
|
||||
MHD_stop_daemon (d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -38,20 +38,22 @@
|
||||
#elif defined(INTPTR_MAX)
|
||||
#define SSIZE_MAX INTPTR_MAX
|
||||
#else
|
||||
#define SSIZE_MAX ((ssize_t)(((size_t)-1)>>1))
|
||||
#define SSIZE_MAX ((ssize_t) (((size_t) -1) >> 1))
|
||||
#endif
|
||||
#endif /* ! SSIZE_MAX */
|
||||
|
||||
#define CHUNK 16384
|
||||
|
||||
struct Holder {
|
||||
FILE *file;
|
||||
z_stream stream;
|
||||
void *buf;
|
||||
struct Holder
|
||||
{
|
||||
FILE *file;
|
||||
z_stream stream;
|
||||
void *buf;
|
||||
};
|
||||
|
||||
static int
|
||||
compress_buf (z_stream *strm, const void *src, size_t src_size, size_t *offset, void **dest, size_t *dest_size,
|
||||
compress_buf (z_stream *strm, const void *src, size_t src_size, size_t *offset,
|
||||
void **dest, size_t *dest_size,
|
||||
void *tmp)
|
||||
{
|
||||
unsigned int have;
|
||||
@@ -61,39 +63,39 @@ compress_buf (z_stream *strm, const void *src, size_t src_size, size_t *offset,
|
||||
*dest = NULL;
|
||||
*dest_size = 0;
|
||||
do
|
||||
{
|
||||
if (src_size > CHUNK)
|
||||
{
|
||||
if (src_size > CHUNK)
|
||||
{
|
||||
strm->avail_in = CHUNK;
|
||||
src_size -= CHUNK;
|
||||
flush = Z_NO_FLUSH;
|
||||
}
|
||||
else
|
||||
{
|
||||
strm->avail_in = (uInt) src_size;
|
||||
flush = Z_SYNC_FLUSH;
|
||||
}
|
||||
*offset += strm->avail_in;
|
||||
strm->next_in = (Bytef *) src;
|
||||
do
|
||||
{
|
||||
strm->avail_out = CHUNK;
|
||||
strm->next_out = tmp;
|
||||
ret = deflate (strm, flush);
|
||||
have = CHUNK - strm->avail_out;
|
||||
*dest_size += have;
|
||||
tmp_dest = realloc (*dest, *dest_size);
|
||||
if (NULL == tmp_dest)
|
||||
{
|
||||
free (*dest);
|
||||
*dest = NULL;
|
||||
return MHD_NO;
|
||||
}
|
||||
*dest = tmp_dest;
|
||||
memcpy ((*dest) + ((*dest_size) - have), tmp, have);
|
||||
}
|
||||
while (0 == strm->avail_out);
|
||||
strm->avail_in = CHUNK;
|
||||
src_size -= CHUNK;
|
||||
flush = Z_NO_FLUSH;
|
||||
}
|
||||
else
|
||||
{
|
||||
strm->avail_in = (uInt) src_size;
|
||||
flush = Z_SYNC_FLUSH;
|
||||
}
|
||||
*offset += strm->avail_in;
|
||||
strm->next_in = (Bytef *) src;
|
||||
do
|
||||
{
|
||||
strm->avail_out = CHUNK;
|
||||
strm->next_out = tmp;
|
||||
ret = deflate (strm, flush);
|
||||
have = CHUNK - strm->avail_out;
|
||||
*dest_size += have;
|
||||
tmp_dest = realloc (*dest, *dest_size);
|
||||
if (NULL == tmp_dest)
|
||||
{
|
||||
free (*dest);
|
||||
*dest = NULL;
|
||||
return MHD_NO;
|
||||
}
|
||||
*dest = tmp_dest;
|
||||
memcpy ((*dest) + ((*dest_size) - have), tmp, have);
|
||||
}
|
||||
while (0 == strm->avail_out);
|
||||
}
|
||||
while (flush != Z_SYNC_FLUSH);
|
||||
return (Z_OK == ret) ? MHD_YES : MHD_NO;
|
||||
}
|
||||
@@ -114,22 +116,23 @@ read_cb (void *cls, uint64_t pos, char *mem, size_t size)
|
||||
return MHD_CONTENT_READER_END_WITH_ERROR;
|
||||
ret = fread (src, 1, size, holder->file);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = MHD_CONTENT_READER_END_WITH_ERROR;
|
||||
goto done;
|
||||
}
|
||||
{
|
||||
ret = MHD_CONTENT_READER_END_WITH_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (0 == size)
|
||||
{
|
||||
ret = MHD_CONTENT_READER_END_OF_STREAM;
|
||||
goto done;
|
||||
}
|
||||
if (MHD_YES != compress_buf (&holder->stream, src, ret, &offset, &buf, &size, holder->buf))
|
||||
{
|
||||
ret = MHD_CONTENT_READER_END_OF_STREAM;
|
||||
goto done;
|
||||
}
|
||||
if (MHD_YES != compress_buf (&holder->stream, src, ret, &offset, &buf, &size,
|
||||
holder->buf))
|
||||
ret = MHD_CONTENT_READER_END_WITH_ERROR;
|
||||
else
|
||||
{
|
||||
memcpy (mem, buf, size);
|
||||
ret = size;
|
||||
}
|
||||
{
|
||||
memcpy (mem, buf, size);
|
||||
ret = size;
|
||||
}
|
||||
free (buf); /* Buf may be set even on error return. */
|
||||
done:
|
||||
free (src);
|
||||
@@ -147,7 +150,8 @@ free_cb (void *cls)
|
||||
}
|
||||
|
||||
static int
|
||||
ahc_echo (void *cls, struct MHD_Connection *con, const char *url, const char *method, const char *version,
|
||||
ahc_echo (void *cls, struct MHD_Connection *con, const char *url, const
|
||||
char *method, const char *version,
|
||||
const char *upload_data, size_t *upload_size, void **ptr)
|
||||
{
|
||||
struct Holder *holder;
|
||||
@@ -160,27 +164,29 @@ ahc_echo (void *cls, struct MHD_Connection *con, const char *url, const char *me
|
||||
(void) upload_data;
|
||||
(void) upload_size;
|
||||
if (NULL == *ptr)
|
||||
{
|
||||
*ptr = (void *) 1;
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
*ptr = (void *) 1;
|
||||
return MHD_YES;
|
||||
}
|
||||
*ptr = NULL;
|
||||
holder = calloc (1, sizeof (struct Holder));
|
||||
if (!holder)
|
||||
if (! holder)
|
||||
return MHD_NO;
|
||||
holder->file = fopen (__FILE__, "rb");
|
||||
if (NULL == holder->file)
|
||||
goto file_error;
|
||||
ret = deflateInit(&holder->stream, Z_BEST_COMPRESSION);
|
||||
ret = deflateInit (&holder->stream, Z_BEST_COMPRESSION);
|
||||
if (ret != Z_OK)
|
||||
goto stream_error;
|
||||
holder->buf = malloc (CHUNK);
|
||||
if (NULL == holder->buf)
|
||||
goto buf_error;
|
||||
res = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, 1024, &read_cb, holder, &free_cb);
|
||||
res = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, 1024, &read_cb,
|
||||
holder, &free_cb);
|
||||
if (NULL == res)
|
||||
goto error;
|
||||
ret = MHD_add_response_header (res, MHD_HTTP_HEADER_CONTENT_ENCODING, "deflate");
|
||||
ret = MHD_add_response_header (res, MHD_HTTP_HEADER_CONTENT_ENCODING,
|
||||
"deflate");
|
||||
if (MHD_YES != ret)
|
||||
goto res_error;
|
||||
ret = MHD_add_response_header (res, MHD_HTTP_HEADER_CONTENT_TYPE, "text/x-c");
|
||||
@@ -209,18 +215,21 @@ main (int argc, char *const *argv)
|
||||
if ((argc != 2) ||
|
||||
(1 != sscanf (argv[1], "%u", &port)) ||
|
||||
(UINT16_MAX < port))
|
||||
{
|
||||
fprintf (stderr, "%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD, (uint16_t) port, NULL, NULL,
|
||||
{
|
||||
fprintf (stderr, "%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD,
|
||||
(uint16_t) port, NULL, NULL,
|
||||
&ahc_echo, NULL,
|
||||
MHD_OPTION_END);
|
||||
if (NULL == d)
|
||||
return 1;
|
||||
if (0 == port)
|
||||
MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT, &port);
|
||||
fprintf (stdout, "HTTP server running at http://localhost:%u\n\nPress ENTER to stop the server ...\n", port);
|
||||
fprintf (stdout,
|
||||
"HTTP server running at http://localhost:%u\n\nPress ENTER to stop the server ...\n",
|
||||
port);
|
||||
(void) getc (stdin);
|
||||
MHD_stop_daemon (d);
|
||||
return 0;
|
||||
|
||||
@@ -77,11 +77,11 @@ body_compress (void **buf,
|
||||
*buf_size);
|
||||
if ((Z_OK != ret) ||
|
||||
(cbuf_size >= *buf_size))
|
||||
{
|
||||
/* compression failed */
|
||||
free (cbuf);
|
||||
return MHD_NO;
|
||||
}
|
||||
{
|
||||
/* compression failed */
|
||||
free (cbuf);
|
||||
return MHD_NO;
|
||||
}
|
||||
free (*buf);
|
||||
*buf = (void *) cbuf;
|
||||
*buf_size = (size_t) cbuf_size;
|
||||
@@ -109,18 +109,18 @@ ahc_echo (void *cls,
|
||||
|
||||
if (0 != strcmp (method, "GET"))
|
||||
return MHD_NO; /* unexpected method */
|
||||
if (!*ptr)
|
||||
{
|
||||
*ptr = (void *) 1;
|
||||
return MHD_YES;
|
||||
}
|
||||
if (! *ptr)
|
||||
{
|
||||
*ptr = (void *) 1;
|
||||
return MHD_YES;
|
||||
}
|
||||
*ptr = NULL;
|
||||
|
||||
body_str = strdup (PAGE);
|
||||
if (NULL == body_str)
|
||||
{
|
||||
return MHD_NO;
|
||||
}
|
||||
{
|
||||
return MHD_NO;
|
||||
}
|
||||
body_len = strlen (body_str);
|
||||
/* try to compress the body */
|
||||
comp = MHD_NO;
|
||||
@@ -132,23 +132,23 @@ ahc_echo (void *cls,
|
||||
body_str,
|
||||
MHD_RESPMEM_MUST_FREE);
|
||||
if (NULL == response)
|
||||
{
|
||||
free (body_str);
|
||||
return MHD_NO;
|
||||
}
|
||||
{
|
||||
free (body_str);
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
if (MHD_YES == comp)
|
||||
{
|
||||
/* Need to indicate to client that body is compressed */
|
||||
if (MHD_NO ==
|
||||
MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_ENCODING,
|
||||
"deflate"))
|
||||
{
|
||||
/* Need to indicate to client that body is compressed */
|
||||
if (MHD_NO ==
|
||||
MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_ENCODING,
|
||||
"deflate"))
|
||||
{
|
||||
MHD_destroy_response (response);
|
||||
return MHD_NO;
|
||||
}
|
||||
MHD_destroy_response (response);
|
||||
return MHD_NO;
|
||||
}
|
||||
}
|
||||
ret = MHD_queue_response (connection,
|
||||
200,
|
||||
response);
|
||||
@@ -162,11 +162,12 @@ main (int argc, char *const *argv)
|
||||
struct MHD_Daemon *d;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD
|
||||
| MHD_USE_ERROR_LOG,
|
||||
atoi (argv[1]), NULL, NULL,
|
||||
&ahc_echo, NULL,
|
||||
MHD_OPTION_END);
|
||||
|
||||
@@ -43,7 +43,8 @@
|
||||
#define CAFILE "ca.pem"
|
||||
#define CRLFILE "crl.pem"
|
||||
|
||||
#define EMPTY_PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"
|
||||
#define EMPTY_PAGE \
|
||||
"<html><head><title>File not found</title></head><body>File not found</body></html>"
|
||||
|
||||
/* Test Certificate */
|
||||
const char cert_pem[] =
|
||||
@@ -117,7 +118,7 @@ http_ahc (void *cls,
|
||||
const char *method,
|
||||
const char *version,
|
||||
const char *upload_data,
|
||||
size_t *upload_data_size, void **ptr)
|
||||
size_t *upload_data_size, void **ptr)
|
||||
{
|
||||
static int aptr;
|
||||
struct MHD_Response *response;
|
||||
@@ -125,60 +126,60 @@ http_ahc (void *cls,
|
||||
FILE *file;
|
||||
int fd;
|
||||
struct stat buf;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
|
||||
return MHD_NO; /* unexpected method */
|
||||
if (&aptr != *ptr)
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
*ptr = NULL; /* reset when done */
|
||||
|
||||
file = fopen (&url[1], "rb");
|
||||
if (NULL != file)
|
||||
{
|
||||
fd = fileno (file);
|
||||
if (-1 == fd)
|
||||
{
|
||||
fd = fileno (file);
|
||||
if (-1 == fd)
|
||||
{
|
||||
(void) fclose (file);
|
||||
return MHD_NO; /* internal error */
|
||||
}
|
||||
if ( (0 != fstat (fd, &buf)) ||
|
||||
(! S_ISREG (buf.st_mode)) )
|
||||
{
|
||||
/* not a regular file, refuse to serve */
|
||||
fclose (file);
|
||||
file = NULL;
|
||||
}
|
||||
(void) fclose (file);
|
||||
return MHD_NO; /* internal error */
|
||||
}
|
||||
if ( (0 != fstat (fd, &buf)) ||
|
||||
(! S_ISREG (buf.st_mode)) )
|
||||
{
|
||||
/* not a regular file, refuse to serve */
|
||||
fclose (file);
|
||||
file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == file)
|
||||
{
|
||||
response = MHD_create_response_from_buffer (strlen (EMPTY_PAGE),
|
||||
(void *) EMPTY_PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
|
||||
MHD_destroy_response (response);
|
||||
}
|
||||
{
|
||||
response = MHD_create_response_from_buffer (strlen (EMPTY_PAGE),
|
||||
(void *) EMPTY_PAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
|
||||
MHD_destroy_response (response);
|
||||
}
|
||||
else
|
||||
{
|
||||
response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k PAGE_NOT_FOUND size */
|
||||
&file_reader, file,
|
||||
&file_free_callback);
|
||||
if (NULL == response)
|
||||
{
|
||||
response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k PAGE_NOT_FOUND size */
|
||||
&file_reader, file,
|
||||
&file_free_callback);
|
||||
if (NULL == response)
|
||||
{
|
||||
fclose (file);
|
||||
return MHD_NO;
|
||||
}
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response (response);
|
||||
fclose (file);
|
||||
return MHD_NO;
|
||||
}
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response (response);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -190,22 +191,23 @@ main (int argc, char *const *argv)
|
||||
int port;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
port = atoi (argv[1]);
|
||||
if ( (1 > port) ||
|
||||
(port > UINT16_MAX) )
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Port must be a number between 1 and 65535\n");
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Port must be a number between 1 and 65535\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
TLS_daemon =
|
||||
MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG |
|
||||
MHD_USE_TLS,
|
||||
MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION
|
||||
| MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG
|
||||
| MHD_USE_TLS,
|
||||
(uint16_t) port,
|
||||
NULL, NULL,
|
||||
&http_ahc, NULL,
|
||||
@@ -214,10 +216,10 @@ main (int argc, char *const *argv)
|
||||
MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
|
||||
MHD_OPTION_END);
|
||||
if (NULL == TLS_daemon)
|
||||
{
|
||||
fprintf (stderr, "Error: failed to start TLS_daemon\n");
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
fprintf (stderr, "Error: failed to start TLS_daemon\n");
|
||||
return 1;
|
||||
}
|
||||
printf ("MHD daemon listening on port %u\n",
|
||||
(unsigned int) port);
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
static ssize_t
|
||||
data_generator (void *cls, uint64_t pos, char *buf, size_t max)
|
||||
{
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)pos; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) pos; /* Unused. Silent compiler warning. */
|
||||
if (max < 80)
|
||||
return 0;
|
||||
memset (buf, 'A', max - 1);
|
||||
@@ -48,20 +48,20 @@ ahc_echo (void *cls,
|
||||
static int aptr;
|
||||
struct MHD_Response *response;
|
||||
int ret;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)url; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) url; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 != strcmp (method, "GET"))
|
||||
return MHD_NO; /* unexpected method */
|
||||
if (&aptr != *ptr)
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
*ptr = NULL; /* reset when done */
|
||||
response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
|
||||
80,
|
||||
@@ -77,11 +77,12 @@ main (int argc, char *const *argv)
|
||||
struct MHD_Daemon *d;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_THREAD_PER_CONNECTION
|
||||
| MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
atoi (argv[1]),
|
||||
NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
|
||||
if (d == NULL)
|
||||
|
||||
+24
-23
@@ -45,29 +45,29 @@
|
||||
|
||||
static int
|
||||
ahc_echo (void *cls,
|
||||
struct MHD_Connection *cnc,
|
||||
const char *url,
|
||||
const char *mt,
|
||||
const char *ver,
|
||||
const char *upd,
|
||||
size_t *upsz,
|
||||
void **ptr)
|
||||
{
|
||||
struct MHD_Connection *cnc,
|
||||
const char *url,
|
||||
const char *mt,
|
||||
const char *ver,
|
||||
const char *upd,
|
||||
size_t *upsz,
|
||||
void **ptr)
|
||||
{
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
error_handler (void *cls,
|
||||
const char *fm,
|
||||
va_list ap)
|
||||
const char *fm,
|
||||
va_list ap)
|
||||
{
|
||||
/* Here we do the translation using GNU gettext.
|
||||
As the error message is from libmicrohttpd, we specify
|
||||
"libmicrohttpd" as the translation domain here. */
|
||||
vprintf (dgettext ("libmicrohttpd",
|
||||
fm),
|
||||
ap);
|
||||
fm),
|
||||
ap);
|
||||
}
|
||||
|
||||
|
||||
@@ -75,21 +75,22 @@ int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
{
|
||||
setlocale(LC_ALL, "");
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
/* The example uses PO files in the directory
|
||||
/* The example uses PO files in the directory
|
||||
"libmicrohttpd/src/examples/locale". This
|
||||
needs to be adapted to match
|
||||
where the MHD PO files are installed. */
|
||||
bindtextdomain ("libmicrohttpd",
|
||||
"locale");
|
||||
MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_FEATURE_MESSAGES | MHD_USE_ERROR_LOG,
|
||||
8080,
|
||||
NULL, NULL,
|
||||
&ahc_echo, NULL,
|
||||
MHD_OPTION_EXTERNAL_LOGGER, &error_handler, NULL,
|
||||
99999 /* invalid option, to raise the error
|
||||
"Invalid option ..." which we are going
|
||||
to translate */);
|
||||
"locale");
|
||||
MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_FEATURE_MESSAGES
|
||||
| MHD_USE_ERROR_LOG,
|
||||
8080,
|
||||
NULL, NULL,
|
||||
&ahc_echo, NULL,
|
||||
MHD_OPTION_EXTERNAL_LOGGER, &error_handler, NULL,
|
||||
99999 /* invalid option, to raise the error
|
||||
"Invalid option ..." which we are going
|
||||
to translate */);
|
||||
return 1; /* This program won't "succeed"... */
|
||||
}
|
||||
|
||||
+258
-251
@@ -32,32 +32,38 @@
|
||||
/**
|
||||
* Invalid method page.
|
||||
*/
|
||||
#define METHOD_ERROR "<html><head><title>Illegal request</title></head><body>Go away.</body></html>"
|
||||
#define METHOD_ERROR \
|
||||
"<html><head><title>Illegal request</title></head><body>Go away.</body></html>"
|
||||
|
||||
/**
|
||||
* Invalid URL page.
|
||||
*/
|
||||
#define NOT_FOUND_ERROR "<html><head><title>Not found</title></head><body>Go away.</body></html>"
|
||||
#define NOT_FOUND_ERROR \
|
||||
"<html><head><title>Not found</title></head><body>Go away.</body></html>"
|
||||
|
||||
/**
|
||||
* Front page. (/)
|
||||
*/
|
||||
#define MAIN_PAGE "<html><head><title>Welcome</title></head><body><form action=\"/2\" method=\"post\">What is your name? <input type=\"text\" name=\"v1\" value=\"%s\" /><input type=\"submit\" value=\"Next\" /></body></html>"
|
||||
#define MAIN_PAGE \
|
||||
"<html><head><title>Welcome</title></head><body><form action=\"/2\" method=\"post\">What is your name? <input type=\"text\" name=\"v1\" value=\"%s\" /><input type=\"submit\" value=\"Next\" /></body></html>"
|
||||
|
||||
/**
|
||||
* Second page. (/2)
|
||||
*/
|
||||
#define SECOND_PAGE "<html><head><title>Tell me more</title></head><body><a href=\"/\">previous</a> <form action=\"/S\" method=\"post\">%s, what is your job? <input type=\"text\" name=\"v2\" value=\"%s\" /><input type=\"submit\" value=\"Next\" /></body></html>"
|
||||
#define SECOND_PAGE \
|
||||
"<html><head><title>Tell me more</title></head><body><a href=\"/\">previous</a> <form action=\"/S\" method=\"post\">%s, what is your job? <input type=\"text\" name=\"v2\" value=\"%s\" /><input type=\"submit\" value=\"Next\" /></body></html>"
|
||||
|
||||
/**
|
||||
* Second page (/S)
|
||||
*/
|
||||
#define SUBMIT_PAGE "<html><head><title>Ready to submit?</title></head><body><form action=\"/F\" method=\"post\"><a href=\"/2\">previous </a> <input type=\"hidden\" name=\"DONE\" value=\"yes\" /><input type=\"submit\" value=\"Submit\" /></body></html>"
|
||||
#define SUBMIT_PAGE \
|
||||
"<html><head><title>Ready to submit?</title></head><body><form action=\"/F\" method=\"post\"><a href=\"/2\">previous </a> <input type=\"hidden\" name=\"DONE\" value=\"yes\" /><input type=\"submit\" value=\"Submit\" /></body></html>"
|
||||
|
||||
/**
|
||||
* Last page.
|
||||
*/
|
||||
#define LAST_PAGE "<html><head><title>Thank you</title></head><body>Thank you.</body></html>"
|
||||
#define LAST_PAGE \
|
||||
"<html><head><title>Thank you</title></head><body>Thank you.</body></html>"
|
||||
|
||||
/**
|
||||
* Name of our cookie.
|
||||
@@ -150,40 +156,40 @@ get_session (struct MHD_Connection *connection)
|
||||
const char *cookie;
|
||||
|
||||
cookie = MHD_lookup_connection_value (connection,
|
||||
MHD_COOKIE_KIND,
|
||||
COOKIE_NAME);
|
||||
MHD_COOKIE_KIND,
|
||||
COOKIE_NAME);
|
||||
if (cookie != NULL)
|
||||
{
|
||||
/* find existing session */
|
||||
ret = sessions;
|
||||
while (NULL != ret)
|
||||
{
|
||||
/* find existing session */
|
||||
ret = sessions;
|
||||
while (NULL != ret)
|
||||
{
|
||||
if (0 == strcmp (cookie, ret->sid))
|
||||
break;
|
||||
ret = ret->next;
|
||||
}
|
||||
if (NULL != ret)
|
||||
{
|
||||
ret->rc++;
|
||||
return ret;
|
||||
}
|
||||
if (0 == strcmp (cookie, ret->sid))
|
||||
break;
|
||||
ret = ret->next;
|
||||
}
|
||||
if (NULL != ret)
|
||||
{
|
||||
ret->rc++;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/* create fresh session */
|
||||
ret = calloc (1, sizeof (struct Session));
|
||||
if (NULL == ret)
|
||||
{
|
||||
fprintf (stderr, "calloc error: %s\n", strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
fprintf (stderr, "calloc error: %s\n", strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
/* not a super-secure way to generate a random session ID,
|
||||
but should do for a simple example... */
|
||||
snprintf (ret->sid,
|
||||
sizeof (ret->sid),
|
||||
"%X%X%X%X",
|
||||
(unsigned int) rand (),
|
||||
(unsigned int) rand (),
|
||||
(unsigned int) rand (),
|
||||
(unsigned int) rand ());
|
||||
sizeof (ret->sid),
|
||||
"%X%X%X%X",
|
||||
(unsigned int) rand (),
|
||||
(unsigned int) rand (),
|
||||
(unsigned int) rand (),
|
||||
(unsigned int) rand ());
|
||||
ret->rc++;
|
||||
ret->start = time (NULL);
|
||||
ret->next = sessions;
|
||||
@@ -202,9 +208,9 @@ get_session (struct MHD_Connection *connection)
|
||||
* @param MHD_YES on success, MHD_NO on failure
|
||||
*/
|
||||
typedef int (*PageHandler)(const void *cls,
|
||||
const char *mime,
|
||||
struct Session *session,
|
||||
struct MHD_Connection *connection);
|
||||
const char *mime,
|
||||
struct Session *session,
|
||||
struct MHD_Connection *connection);
|
||||
|
||||
|
||||
/**
|
||||
@@ -242,22 +248,22 @@ struct Page
|
||||
*/
|
||||
static void
|
||||
add_session_cookie (struct Session *session,
|
||||
struct MHD_Response *response)
|
||||
struct MHD_Response *response)
|
||||
{
|
||||
char cstr[256];
|
||||
snprintf (cstr,
|
||||
sizeof (cstr),
|
||||
"%s=%s",
|
||||
COOKIE_NAME,
|
||||
session->sid);
|
||||
sizeof (cstr),
|
||||
"%s=%s",
|
||||
COOKIE_NAME,
|
||||
session->sid);
|
||||
if (MHD_NO ==
|
||||
MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_SET_COOKIE,
|
||||
cstr))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to set session cookie header!\n");
|
||||
}
|
||||
MHD_HTTP_HEADER_SET_COOKIE,
|
||||
cstr))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to set session cookie header!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -272,9 +278,9 @@ add_session_cookie (struct Session *session,
|
||||
*/
|
||||
static int
|
||||
serve_simple_form (const void *cls,
|
||||
const char *mime,
|
||||
struct Session *session,
|
||||
struct MHD_Connection *connection)
|
||||
const char *mime,
|
||||
struct Session *session,
|
||||
struct MHD_Connection *connection)
|
||||
{
|
||||
int ret;
|
||||
const char *form = cls;
|
||||
@@ -282,17 +288,17 @@ serve_simple_form (const void *cls,
|
||||
|
||||
/* return static form */
|
||||
response = MHD_create_response_from_buffer (strlen (form),
|
||||
(void *) form,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
(void *) form,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
if (NULL == response)
|
||||
return MHD_NO;
|
||||
add_session_cookie (session, response);
|
||||
MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_ENCODING,
|
||||
mime);
|
||||
MHD_HTTP_HEADER_CONTENT_ENCODING,
|
||||
mime);
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_OK,
|
||||
response);
|
||||
MHD_HTTP_OK,
|
||||
response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
}
|
||||
@@ -308,28 +314,28 @@ serve_simple_form (const void *cls,
|
||||
*/
|
||||
static int
|
||||
fill_v1_form (const void *cls,
|
||||
const char *mime,
|
||||
struct Session *session,
|
||||
struct MHD_Connection *connection)
|
||||
const char *mime,
|
||||
struct Session *session,
|
||||
struct MHD_Connection *connection)
|
||||
{
|
||||
int ret;
|
||||
size_t slen;
|
||||
char *reply;
|
||||
struct MHD_Response *response;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
|
||||
slen = strlen (MAIN_PAGE) + strlen (session->value_1);
|
||||
reply = malloc (slen + 1);
|
||||
if (NULL == reply)
|
||||
return MHD_NO;
|
||||
snprintf (reply,
|
||||
slen + 1,
|
||||
MAIN_PAGE,
|
||||
session->value_1);
|
||||
slen + 1,
|
||||
MAIN_PAGE,
|
||||
session->value_1);
|
||||
/* return static form */
|
||||
response = MHD_create_response_from_buffer (slen,
|
||||
(void *) reply,
|
||||
MHD_RESPMEM_MUST_FREE);
|
||||
(void *) reply,
|
||||
MHD_RESPMEM_MUST_FREE);
|
||||
if (NULL == response)
|
||||
{
|
||||
free (reply);
|
||||
@@ -337,11 +343,11 @@ fill_v1_form (const void *cls,
|
||||
}
|
||||
add_session_cookie (session, response);
|
||||
MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_ENCODING,
|
||||
mime);
|
||||
MHD_HTTP_HEADER_CONTENT_ENCODING,
|
||||
mime);
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_OK,
|
||||
response);
|
||||
MHD_HTTP_OK,
|
||||
response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
}
|
||||
@@ -357,29 +363,30 @@ fill_v1_form (const void *cls,
|
||||
*/
|
||||
static int
|
||||
fill_v1_v2_form (const void *cls,
|
||||
const char *mime,
|
||||
struct Session *session,
|
||||
struct MHD_Connection *connection)
|
||||
const char *mime,
|
||||
struct Session *session,
|
||||
struct MHD_Connection *connection)
|
||||
{
|
||||
int ret;
|
||||
char *reply;
|
||||
struct MHD_Response *response;
|
||||
size_t slen;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
|
||||
slen = strlen (SECOND_PAGE) + strlen (session->value_1) + strlen (session->value_2);
|
||||
slen = strlen (SECOND_PAGE) + strlen (session->value_1) + strlen (
|
||||
session->value_2);
|
||||
reply = malloc (slen + 1);
|
||||
if (NULL == reply)
|
||||
return MHD_NO;
|
||||
snprintf (reply,
|
||||
slen + 1,
|
||||
SECOND_PAGE,
|
||||
session->value_1,
|
||||
slen + 1,
|
||||
SECOND_PAGE,
|
||||
session->value_1,
|
||||
session->value_2);
|
||||
/* return static form */
|
||||
response = MHD_create_response_from_buffer (slen,
|
||||
(void *) reply,
|
||||
MHD_RESPMEM_MUST_FREE);
|
||||
(void *) reply,
|
||||
MHD_RESPMEM_MUST_FREE);
|
||||
if (NULL == response)
|
||||
{
|
||||
free (reply);
|
||||
@@ -387,11 +394,11 @@ fill_v1_v2_form (const void *cls,
|
||||
}
|
||||
add_session_cookie (session, response);
|
||||
MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_ENCODING,
|
||||
mime);
|
||||
MHD_HTTP_HEADER_CONTENT_ENCODING,
|
||||
mime);
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_OK,
|
||||
response);
|
||||
MHD_HTTP_OK,
|
||||
response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
}
|
||||
@@ -407,27 +414,27 @@ fill_v1_v2_form (const void *cls,
|
||||
*/
|
||||
static int
|
||||
not_found_page (const void *cls,
|
||||
const char *mime,
|
||||
struct Session *session,
|
||||
struct MHD_Connection *connection)
|
||||
const char *mime,
|
||||
struct Session *session,
|
||||
struct MHD_Connection *connection)
|
||||
{
|
||||
int ret;
|
||||
struct MHD_Response *response;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)session; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) session; /* Unused. Silent compiler warning. */
|
||||
|
||||
/* unsupported HTTP method */
|
||||
response = MHD_create_response_from_buffer (strlen (NOT_FOUND_ERROR),
|
||||
(void *) NOT_FOUND_ERROR,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
(void *) NOT_FOUND_ERROR,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
if (NULL == response)
|
||||
return MHD_NO;
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
response);
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
response);
|
||||
MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_ENCODING,
|
||||
mime);
|
||||
MHD_HTTP_HEADER_CONTENT_ENCODING,
|
||||
mime);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
}
|
||||
@@ -436,14 +443,13 @@ not_found_page (const void *cls,
|
||||
/**
|
||||
* List of all pages served by this HTTP server.
|
||||
*/
|
||||
static struct Page pages[] =
|
||||
{
|
||||
{ "/", "text/html", &fill_v1_form, NULL },
|
||||
{ "/2", "text/html", &fill_v1_v2_form, NULL },
|
||||
{ "/S", "text/html", &serve_simple_form, SUBMIT_PAGE },
|
||||
{ "/F", "text/html", &serve_simple_form, LAST_PAGE },
|
||||
{ NULL, NULL, ¬_found_page, NULL } /* 404 */
|
||||
};
|
||||
static struct Page pages[] = {
|
||||
{ "/", "text/html", &fill_v1_form, NULL },
|
||||
{ "/2", "text/html", &fill_v1_v2_form, NULL },
|
||||
{ "/S", "text/html", &serve_simple_form, SUBMIT_PAGE },
|
||||
{ "/F", "text/html", &serve_simple_form, LAST_PAGE },
|
||||
{ NULL, NULL, ¬_found_page, NULL } /* 404 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -468,49 +474,49 @@ static struct Page pages[] =
|
||||
*/
|
||||
static int
|
||||
post_iterator (void *cls,
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
const char *filename,
|
||||
const char *content_type,
|
||||
const char *transfer_encoding,
|
||||
const char *data, uint64_t off, size_t size)
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
const char *filename,
|
||||
const char *content_type,
|
||||
const char *transfer_encoding,
|
||||
const char *data, uint64_t off, size_t size)
|
||||
{
|
||||
struct Request *request = cls;
|
||||
struct Session *session = request->session;
|
||||
(void)kind; /* Unused. Silent compiler warning. */
|
||||
(void)filename; /* Unused. Silent compiler warning. */
|
||||
(void)content_type; /* Unused. Silent compiler warning. */
|
||||
(void)transfer_encoding; /* Unused. Silent compiler warning. */
|
||||
(void) kind; /* Unused. Silent compiler warning. */
|
||||
(void) filename; /* Unused. Silent compiler warning. */
|
||||
(void) content_type; /* Unused. Silent compiler warning. */
|
||||
(void) transfer_encoding; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 == strcmp ("DONE", key))
|
||||
{
|
||||
fprintf (stdout,
|
||||
"Session `%s' submitted `%s', `%s'\n",
|
||||
session->sid,
|
||||
session->value_1,
|
||||
session->value_2);
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
fprintf (stdout,
|
||||
"Session `%s' submitted `%s', `%s'\n",
|
||||
session->sid,
|
||||
session->value_1,
|
||||
session->value_2);
|
||||
return MHD_YES;
|
||||
}
|
||||
if (0 == strcmp ("v1", key))
|
||||
{
|
||||
if (size + off >= sizeof(session->value_1))
|
||||
size = sizeof (session->value_1) - off - 1;
|
||||
memcpy (&session->value_1[off],
|
||||
data,
|
||||
size);
|
||||
session->value_1[size+off] = '\0';
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
if (size + off >= sizeof(session->value_1))
|
||||
size = sizeof (session->value_1) - off - 1;
|
||||
memcpy (&session->value_1[off],
|
||||
data,
|
||||
size);
|
||||
session->value_1[size + off] = '\0';
|
||||
return MHD_YES;
|
||||
}
|
||||
if (0 == strcmp ("v2", key))
|
||||
{
|
||||
if (size + off >= sizeof(session->value_2))
|
||||
size = sizeof (session->value_2) - off - 1;
|
||||
memcpy (&session->value_2[off],
|
||||
data,
|
||||
size);
|
||||
session->value_2[size+off] = '\0';
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
if (size + off >= sizeof(session->value_2))
|
||||
size = sizeof (session->value_2) - off - 1;
|
||||
memcpy (&session->value_2[off],
|
||||
data,
|
||||
size);
|
||||
session->value_2[size + off] = '\0';
|
||||
return MHD_YES;
|
||||
}
|
||||
fprintf (stderr,
|
||||
"Unsupported form value `%s'\n",
|
||||
key);
|
||||
@@ -553,99 +559,99 @@ post_iterator (void *cls,
|
||||
*/
|
||||
static int
|
||||
create_response (void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
const char *url,
|
||||
const char *method,
|
||||
const char *version,
|
||||
const char *upload_data,
|
||||
size_t *upload_data_size,
|
||||
void **ptr)
|
||||
struct MHD_Connection *connection,
|
||||
const char *url,
|
||||
const char *method,
|
||||
const char *version,
|
||||
const char *upload_data,
|
||||
size_t *upload_data_size,
|
||||
void **ptr)
|
||||
{
|
||||
struct MHD_Response *response;
|
||||
struct Request *request;
|
||||
struct Session *session;
|
||||
int ret;
|
||||
unsigned int i;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
|
||||
request = *ptr;
|
||||
if (NULL == request)
|
||||
{
|
||||
request = calloc (1, sizeof (struct Request));
|
||||
if (NULL == request)
|
||||
{
|
||||
request = calloc (1, sizeof (struct Request));
|
||||
if (NULL == request)
|
||||
{
|
||||
fprintf (stderr, "calloc error: %s\n", strerror (errno));
|
||||
return MHD_NO;
|
||||
}
|
||||
*ptr = request;
|
||||
if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
|
||||
{
|
||||
request->pp = MHD_create_post_processor (connection, 1024,
|
||||
&post_iterator, request);
|
||||
if (NULL == request->pp)
|
||||
{
|
||||
fprintf (stderr, "Failed to setup post processor for `%s'\n",
|
||||
url);
|
||||
return MHD_NO; /* internal error */
|
||||
}
|
||||
}
|
||||
return MHD_YES;
|
||||
fprintf (stderr, "calloc error: %s\n", strerror (errno));
|
||||
return MHD_NO;
|
||||
}
|
||||
*ptr = request;
|
||||
if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
|
||||
{
|
||||
request->pp = MHD_create_post_processor (connection, 1024,
|
||||
&post_iterator, request);
|
||||
if (NULL == request->pp)
|
||||
{
|
||||
fprintf (stderr, "Failed to setup post processor for `%s'\n",
|
||||
url);
|
||||
return MHD_NO; /* internal error */
|
||||
}
|
||||
}
|
||||
return MHD_YES;
|
||||
}
|
||||
if (NULL == request->session)
|
||||
{
|
||||
request->session = get_session (connection);
|
||||
if (NULL == request->session)
|
||||
{
|
||||
request->session = get_session (connection);
|
||||
if (NULL == request->session)
|
||||
{
|
||||
fprintf (stderr, "Failed to setup session for `%s'\n",
|
||||
url);
|
||||
return MHD_NO; /* internal error */
|
||||
}
|
||||
fprintf (stderr, "Failed to setup session for `%s'\n",
|
||||
url);
|
||||
return MHD_NO; /* internal error */
|
||||
}
|
||||
}
|
||||
session = request->session;
|
||||
session->start = time (NULL);
|
||||
if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
|
||||
{
|
||||
/* evaluate POST data */
|
||||
MHD_post_process (request->pp,
|
||||
upload_data,
|
||||
*upload_data_size);
|
||||
if (0 != *upload_data_size)
|
||||
{
|
||||
/* evaluate POST data */
|
||||
MHD_post_process (request->pp,
|
||||
upload_data,
|
||||
*upload_data_size);
|
||||
if (0 != *upload_data_size)
|
||||
{
|
||||
*upload_data_size = 0;
|
||||
return MHD_YES;
|
||||
}
|
||||
/* done with POST data, serve response */
|
||||
MHD_destroy_post_processor (request->pp);
|
||||
request->pp = NULL;
|
||||
method = MHD_HTTP_METHOD_GET; /* fake 'GET' */
|
||||
if (NULL != request->post_url)
|
||||
url = request->post_url;
|
||||
*upload_data_size = 0;
|
||||
return MHD_YES;
|
||||
}
|
||||
/* done with POST data, serve response */
|
||||
MHD_destroy_post_processor (request->pp);
|
||||
request->pp = NULL;
|
||||
method = MHD_HTTP_METHOD_GET; /* fake 'GET' */
|
||||
if (NULL != request->post_url)
|
||||
url = request->post_url;
|
||||
}
|
||||
|
||||
if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) ||
|
||||
(0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) )
|
||||
{
|
||||
/* find out which page to serve */
|
||||
i=0;
|
||||
while ( (pages[i].url != NULL) &&
|
||||
(0 != strcmp (pages[i].url, url)) )
|
||||
i++;
|
||||
ret = pages[i].handler (pages[i].handler_cls,
|
||||
pages[i].mime,
|
||||
session, connection);
|
||||
if (ret != MHD_YES)
|
||||
fprintf (stderr, "Failed to create page for `%s'\n",
|
||||
url);
|
||||
return ret;
|
||||
}
|
||||
{
|
||||
/* find out which page to serve */
|
||||
i = 0;
|
||||
while ( (pages[i].url != NULL) &&
|
||||
(0 != strcmp (pages[i].url, url)) )
|
||||
i++;
|
||||
ret = pages[i].handler (pages[i].handler_cls,
|
||||
pages[i].mime,
|
||||
session, connection);
|
||||
if (ret != MHD_YES)
|
||||
fprintf (stderr, "Failed to create page for `%s'\n",
|
||||
url);
|
||||
return ret;
|
||||
}
|
||||
/* unsupported HTTP method */
|
||||
response = MHD_create_response_from_buffer (strlen (METHOD_ERROR),
|
||||
(void *) METHOD_ERROR,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
(void *) METHOD_ERROR,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_NOT_ACCEPTABLE,
|
||||
response);
|
||||
MHD_HTTP_NOT_ACCEPTABLE,
|
||||
response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
}
|
||||
@@ -662,14 +668,14 @@ create_response (void *cls,
|
||||
*/
|
||||
static void
|
||||
request_completed_callback (void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
void **con_cls,
|
||||
enum MHD_RequestTerminationCode toe)
|
||||
struct MHD_Connection *connection,
|
||||
void **con_cls,
|
||||
enum MHD_RequestTerminationCode toe)
|
||||
{
|
||||
struct Request *request = *con_cls;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)connection; /* Unused. Silent compiler warning. */
|
||||
(void)toe; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) connection; /* Unused. Silent compiler warning. */
|
||||
(void) toe; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (NULL == request)
|
||||
return;
|
||||
@@ -697,21 +703,21 @@ expire_sessions ()
|
||||
prev = NULL;
|
||||
pos = sessions;
|
||||
while (NULL != pos)
|
||||
{
|
||||
next = pos->next;
|
||||
if (now - pos->start > 60 * 60)
|
||||
{
|
||||
next = pos->next;
|
||||
if (now - pos->start > 60 * 60)
|
||||
{
|
||||
/* expire sessions after 1h */
|
||||
if (NULL == prev)
|
||||
sessions = pos->next;
|
||||
else
|
||||
prev->next = next;
|
||||
free (pos);
|
||||
}
|
||||
/* expire sessions after 1h */
|
||||
if (NULL == prev)
|
||||
sessions = pos->next;
|
||||
else
|
||||
prev = pos;
|
||||
pos = next;
|
||||
prev->next = next;
|
||||
free (pos);
|
||||
}
|
||||
else
|
||||
prev = pos;
|
||||
pos = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -732,45 +738,46 @@ main (int argc, char *const *argv)
|
||||
MHD_UNSIGNED_LONG_LONG mhd_timeout;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
/* initialize PRNG */
|
||||
srand ((unsigned int) time (NULL));
|
||||
d = MHD_start_daemon (MHD_USE_ERROR_LOG,
|
||||
atoi (argv[1]),
|
||||
NULL, NULL,
|
||||
&create_response, NULL,
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 15,
|
||||
MHD_OPTION_NOTIFY_COMPLETED, &request_completed_callback, NULL,
|
||||
MHD_OPTION_END);
|
||||
&create_response, NULL,
|
||||
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 15,
|
||||
MHD_OPTION_NOTIFY_COMPLETED,
|
||||
&request_completed_callback, NULL,
|
||||
MHD_OPTION_END);
|
||||
if (NULL == d)
|
||||
return 1;
|
||||
while (1)
|
||||
{
|
||||
expire_sessions ();
|
||||
max = 0;
|
||||
FD_ZERO (&rs);
|
||||
FD_ZERO (&ws);
|
||||
FD_ZERO (&es);
|
||||
if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
|
||||
break; /* fatal internal error */
|
||||
if (MHD_get_timeout (d, &mhd_timeout) == MHD_YES)
|
||||
{
|
||||
expire_sessions ();
|
||||
max = 0;
|
||||
FD_ZERO (&rs);
|
||||
FD_ZERO (&ws);
|
||||
FD_ZERO (&es);
|
||||
if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
|
||||
break; /* fatal internal error */
|
||||
if (MHD_get_timeout (d, &mhd_timeout) == MHD_YES)
|
||||
{
|
||||
tv.tv_sec = mhd_timeout / 1000;
|
||||
tv.tv_usec = (mhd_timeout - (tv.tv_sec * 1000)) * 1000;
|
||||
tvp = &tv;
|
||||
}
|
||||
else
|
||||
tvp = NULL;
|
||||
if (-1 == select (max + 1, &rs, &ws, &es, tvp))
|
||||
{
|
||||
if (EINTR != errno)
|
||||
abort ();
|
||||
}
|
||||
MHD_run (d);
|
||||
tv.tv_sec = mhd_timeout / 1000;
|
||||
tv.tv_usec = (mhd_timeout - (tv.tv_sec * 1000)) * 1000;
|
||||
tvp = &tv;
|
||||
}
|
||||
else
|
||||
tvp = NULL;
|
||||
if (-1 == select (max + 1, &rs, &ws, &es, tvp))
|
||||
{
|
||||
if (EINTR != errno)
|
||||
abort ();
|
||||
}
|
||||
MHD_run (d);
|
||||
}
|
||||
MHD_stop_daemon (d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
#include "platform.h"
|
||||
#include <microhttpd.h>
|
||||
|
||||
#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>Query string for "%s" was "%s"</body></html>"
|
||||
#define PAGE \
|
||||
"<html><head><title>libmicrohttpd demo</title></head><body>Query string for "%s" was "%s"</body></html>"
|
||||
|
||||
static int
|
||||
ahc_echo (void *cls,
|
||||
@@ -42,19 +43,19 @@ ahc_echo (void *cls,
|
||||
char *me;
|
||||
struct MHD_Response *response;
|
||||
int ret;
|
||||
(void)url; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) url; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 != strcmp (method, "GET"))
|
||||
return MHD_NO; /* unexpected method */
|
||||
if (&aptr != *ptr)
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
*ptr = NULL; /* reset when done */
|
||||
val = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "q");
|
||||
me = malloc (snprintf (NULL, 0, fmt, "q", val) + 1);
|
||||
@@ -62,12 +63,12 @@ ahc_echo (void *cls,
|
||||
return MHD_NO;
|
||||
sprintf (me, fmt, "q", val);
|
||||
response = MHD_create_response_from_buffer (strlen (me), me,
|
||||
MHD_RESPMEM_MUST_FREE);
|
||||
MHD_RESPMEM_MUST_FREE);
|
||||
if (response == NULL)
|
||||
{
|
||||
free (me);
|
||||
return MHD_NO;
|
||||
}
|
||||
{
|
||||
free (me);
|
||||
return MHD_NO;
|
||||
}
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
@@ -80,18 +81,19 @@ main (int argc, char *const *argv)
|
||||
int port;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
port = atoi (argv[1]);
|
||||
if ( (port < 0) ||
|
||||
(port > UINT16_MAX) )
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION
|
||||
| MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
(uint16_t) port,
|
||||
NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
|
||||
if (NULL == d)
|
||||
|
||||
@@ -24,14 +24,16 @@
|
||||
#include "platform.h"
|
||||
#include <microhttpd.h>
|
||||
|
||||
const char *askpage = "<html><body>\n\
|
||||
const char *askpage =
|
||||
"<html><body>\n\
|
||||
Upload a file, please!<br>\n\
|
||||
<form action=\"/filepost\" method=\"post\" enctype=\"multipart/form-data\">\n\
|
||||
<input name=\"file\" type=\"file\">\n\
|
||||
<input type=\"submit\" value=\" Send \"></form>\n\
|
||||
</body></html>";
|
||||
|
||||
#define BUSYPAGE "<html><head><title>Webserver busy</title></head><body>We are too busy to process POSTs right now.</body></html>"
|
||||
#define BUSYPAGE \
|
||||
"<html><head><title>Webserver busy</title></head><body>We are too busy to process POSTs right now.</body></html>"
|
||||
|
||||
static int
|
||||
ahc_echo (void *cls,
|
||||
@@ -45,37 +47,37 @@ ahc_echo (void *cls,
|
||||
const char *me = cls;
|
||||
struct MHD_Response *response;
|
||||
int ret;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)url; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) url; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
|
||||
if ((0 != strcmp (method, "GET")) && (0 != strcmp (method, "POST")))
|
||||
return MHD_NO; /* unexpected method */
|
||||
|
||||
if (&aptr != *ptr)
|
||||
{
|
||||
*ptr = &aptr;
|
||||
{
|
||||
*ptr = &aptr;
|
||||
|
||||
/* always to busy for POST requests */
|
||||
if (0 == strcmp (method, "POST"))
|
||||
{
|
||||
response = MHD_create_response_from_buffer (strlen (BUSYPAGE),
|
||||
(void *) BUSYPAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret =
|
||||
MHD_queue_response (connection, MHD_HTTP_SERVICE_UNAVAILABLE,
|
||||
response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
}
|
||||
/* always to busy for POST requests */
|
||||
if (0 == strcmp (method, "POST"))
|
||||
{
|
||||
response = MHD_create_response_from_buffer (strlen (BUSYPAGE),
|
||||
(void *) BUSYPAGE,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret =
|
||||
MHD_queue_response (connection, MHD_HTTP_SERVICE_UNAVAILABLE,
|
||||
response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
*ptr = NULL; /* reset when done */
|
||||
response = MHD_create_response_from_buffer (strlen (me),
|
||||
(void *) me,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
(void *) me,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
@@ -87,11 +89,12 @@ main (int argc, char *const *argv)
|
||||
struct MHD_Daemon *d;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION
|
||||
| MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
atoi (argv[1]),
|
||||
NULL, NULL, &ahc_echo, (void *) askpage,
|
||||
MHD_OPTION_END);
|
||||
|
||||
@@ -31,7 +31,8 @@
|
||||
|
||||
#define TIMEOUT_INFINITE -1
|
||||
|
||||
struct Request {
|
||||
struct Request
|
||||
{
|
||||
struct MHD_Connection *connection;
|
||||
int timerfd;
|
||||
};
|
||||
@@ -52,7 +53,7 @@ ahc_echo (void *cls,
|
||||
{
|
||||
struct MHD_Response *response;
|
||||
int ret;
|
||||
struct Request* req;
|
||||
struct Request*req;
|
||||
struct itimerspec ts;
|
||||
|
||||
(void) cls;
|
||||
@@ -89,29 +90,29 @@ ahc_echo (void *cls,
|
||||
return ret;
|
||||
}
|
||||
/* create timer and suspend connection */
|
||||
req->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
|
||||
req->timerfd = timerfd_create (CLOCK_MONOTONIC, TFD_NONBLOCK);
|
||||
if (-1 == req->timerfd)
|
||||
{
|
||||
printf("timerfd_create: %s", strerror(errno));
|
||||
return MHD_NO;
|
||||
}
|
||||
{
|
||||
printf ("timerfd_create: %s", strerror (errno));
|
||||
return MHD_NO;
|
||||
}
|
||||
evt.events = EPOLLIN;
|
||||
evt.data.ptr = req;
|
||||
if (-1 == epoll_ctl(epfd, EPOLL_CTL_ADD, req->timerfd, &evt))
|
||||
{
|
||||
printf("epoll_ctl: %s", strerror(errno));
|
||||
return MHD_NO;
|
||||
}
|
||||
if (-1 == epoll_ctl (epfd, EPOLL_CTL_ADD, req->timerfd, &evt))
|
||||
{
|
||||
printf ("epoll_ctl: %s", strerror (errno));
|
||||
return MHD_NO;
|
||||
}
|
||||
ts.it_value.tv_sec = 1;
|
||||
ts.it_value.tv_nsec = 0;
|
||||
ts.it_interval.tv_sec = 0;
|
||||
ts.it_interval.tv_nsec = 0;
|
||||
if (-1 == timerfd_settime(req->timerfd, 0, &ts, NULL))
|
||||
{
|
||||
printf("timerfd_settime: %s", strerror(errno));
|
||||
return MHD_NO;
|
||||
}
|
||||
MHD_suspend_connection(connection);
|
||||
if (-1 == timerfd_settime (req->timerfd, 0, &ts, NULL))
|
||||
{
|
||||
printf ("timerfd_settime: %s", strerror (errno));
|
||||
return MHD_NO;
|
||||
}
|
||||
MHD_suspend_connection (connection);
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
@@ -130,7 +131,7 @@ connection_done (void *cls,
|
||||
if (-1 != req->timerfd)
|
||||
if (0 != close (req->timerfd))
|
||||
abort ();
|
||||
free(req);
|
||||
free (req);
|
||||
}
|
||||
|
||||
|
||||
@@ -139,17 +140,17 @@ main (int argc,
|
||||
char *const *argv)
|
||||
{
|
||||
struct MHD_Daemon *d;
|
||||
const union MHD_DaemonInfo * info;
|
||||
const union MHD_DaemonInfo *info;
|
||||
int current_event_count;
|
||||
struct epoll_event events_list[1];
|
||||
struct Request *req;
|
||||
uint64_t timer_expirations;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_USE_EPOLL | MHD_ALLOW_SUSPEND_RESUME,
|
||||
atoi (argv[1]),
|
||||
NULL, NULL, &ahc_echo, NULL,
|
||||
@@ -158,17 +159,17 @@ main (int argc,
|
||||
if (d == NULL)
|
||||
return 1;
|
||||
|
||||
info = MHD_get_daemon_info(d, MHD_DAEMON_INFO_EPOLL_FD);
|
||||
info = MHD_get_daemon_info (d, MHD_DAEMON_INFO_EPOLL_FD);
|
||||
if (info == NULL)
|
||||
return 1;
|
||||
|
||||
epfd = epoll_create1(EPOLL_CLOEXEC);
|
||||
epfd = epoll_create1 (EPOLL_CLOEXEC);
|
||||
if (-1 == epfd)
|
||||
return 1;
|
||||
|
||||
evt.events = EPOLLIN;
|
||||
evt.data.ptr = NULL;
|
||||
if (-1 == epoll_ctl(epfd, EPOLL_CTL_ADD, info->epoll_fd, &evt))
|
||||
if (-1 == epoll_ctl (epfd, EPOLL_CTL_ADD, info->epoll_fd, &evt))
|
||||
return 1;
|
||||
|
||||
while (1)
|
||||
@@ -182,7 +183,7 @@ main (int argc,
|
||||
timeout = TIMEOUT_INFINITE;
|
||||
else
|
||||
timeout = (to < INT_MAX - 1) ? (int) to : (INT_MAX - 1);
|
||||
current_event_count = epoll_wait(epfd, events_list, 1, timeout);
|
||||
current_event_count = epoll_wait (epfd, events_list, 1, timeout);
|
||||
|
||||
if (1 == current_event_count)
|
||||
{
|
||||
@@ -191,12 +192,13 @@ main (int argc,
|
||||
/* A timer has timed out */
|
||||
req = events_list[0].data.ptr;
|
||||
/* read from the fd so the system knows we heard the notice */
|
||||
if (-1 == read(req->timerfd, &timer_expirations, sizeof(timer_expirations)))
|
||||
if (-1 == read (req->timerfd, &timer_expirations,
|
||||
sizeof(timer_expirations)))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
/* Now resume the connection */
|
||||
MHD_resume_connection(req->connection);
|
||||
MHD_resume_connection (req->connection);
|
||||
}
|
||||
}
|
||||
else if (0 == current_event_count)
|
||||
@@ -208,7 +210,7 @@ main (int argc,
|
||||
/* error */
|
||||
return 1;
|
||||
}
|
||||
if (! MHD_run(d))
|
||||
if (! MHD_run (d))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+20
-19
@@ -30,27 +30,27 @@
|
||||
#define PORT 8080
|
||||
|
||||
static int
|
||||
answer_to_connection(void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
const char *url,
|
||||
const char *method,
|
||||
const char *version,
|
||||
const char *upload_data,
|
||||
size_t *upload_data_size,
|
||||
void **con_cls)
|
||||
answer_to_connection (void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
const char *url,
|
||||
const char *method,
|
||||
const char *version,
|
||||
const char *upload_data,
|
||||
size_t *upload_data_size,
|
||||
void **con_cls)
|
||||
{
|
||||
const char *page = "<html><body>Hello timeout!</body></html>";
|
||||
struct MHD_Response *response;
|
||||
int ret;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)url; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)method; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void)con_cls; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) url; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) method; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) con_cls; /* Unused. Silent compiler warning. */
|
||||
|
||||
response = MHD_create_response_from_buffer (strlen(page),
|
||||
response = MHD_create_response_from_buffer (strlen (page),
|
||||
(void *) page,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
MHD_add_response_header (response,
|
||||
@@ -59,7 +59,7 @@ answer_to_connection(void *cls,
|
||||
ret = MHD_queue_response (connection,
|
||||
MHD_HTTP_OK,
|
||||
response);
|
||||
MHD_destroy_response(response);
|
||||
MHD_destroy_response (response);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,8 @@ main (void)
|
||||
{
|
||||
struct MHD_Daemon *daemon;
|
||||
|
||||
daemon = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD,
|
||||
daemon = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION
|
||||
| MHD_USE_INTERNAL_POLLING_THREAD,
|
||||
PORT,
|
||||
NULL, NULL,
|
||||
&answer_to_connection, NULL,
|
||||
@@ -78,7 +79,7 @@ main (void)
|
||||
MHD_OPTION_END);
|
||||
if (NULL == daemon)
|
||||
return 1;
|
||||
(void) getchar();
|
||||
(void) getchar ();
|
||||
MHD_stop_daemon (daemon);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
#include <microhttpd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
|
||||
#define PAGE \
|
||||
"<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
|
||||
|
||||
|
||||
/**
|
||||
@@ -72,23 +73,23 @@ send_all (MHD_socket sock,
|
||||
|
||||
make_blocking (sock);
|
||||
for (off = 0; off < len; off += ret)
|
||||
{
|
||||
ret = send (sock,
|
||||
&buf[off],
|
||||
len - off,
|
||||
0);
|
||||
if (0 > ret)
|
||||
{
|
||||
ret = send (sock,
|
||||
&buf[off],
|
||||
len - off,
|
||||
0);
|
||||
if (0 > ret)
|
||||
{
|
||||
if (EAGAIN == errno)
|
||||
{
|
||||
ret = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (0 == ret)
|
||||
break;
|
||||
if (EAGAIN == errno)
|
||||
{
|
||||
ret = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (0 == ret)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -118,25 +119,25 @@ run_usock (void *cls)
|
||||
make_blocking (md->sock);
|
||||
/* start by sending extra data MHD may have already read, if any */
|
||||
if (0 != md->extra_in_size)
|
||||
{
|
||||
send_all (md->sock,
|
||||
md->extra_in,
|
||||
md->extra_in_size);
|
||||
free (md->extra_in);
|
||||
}
|
||||
{
|
||||
send_all (md->sock,
|
||||
md->extra_in,
|
||||
md->extra_in_size);
|
||||
free (md->extra_in);
|
||||
}
|
||||
/* now echo in a loop */
|
||||
while (1)
|
||||
{
|
||||
got = recv (md->sock,
|
||||
buf,
|
||||
sizeof (buf),
|
||||
0);
|
||||
if (0 >= got)
|
||||
break;
|
||||
send_all (md->sock,
|
||||
{
|
||||
got = recv (md->sock,
|
||||
buf,
|
||||
got);
|
||||
}
|
||||
sizeof (buf),
|
||||
0);
|
||||
if (0 >= got)
|
||||
break;
|
||||
send_all (md->sock,
|
||||
buf,
|
||||
got);
|
||||
}
|
||||
free (md);
|
||||
MHD_upgrade_action (urh,
|
||||
MHD_UPGRADE_ACTION_CLOSE);
|
||||
@@ -202,23 +203,23 @@ uh_cb (void *cls,
|
||||
{
|
||||
struct MyData *md;
|
||||
pthread_t pt;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)connection; /* Unused. Silent compiler warning. */
|
||||
(void)con_cls; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) connection; /* Unused. Silent compiler warning. */
|
||||
(void) con_cls; /* Unused. Silent compiler warning. */
|
||||
|
||||
md = malloc (sizeof (struct MyData));
|
||||
if (NULL == md)
|
||||
abort ();
|
||||
memset (md, 0, sizeof (struct MyData));
|
||||
if (0 != extra_in_size)
|
||||
{
|
||||
md->extra_in = malloc (extra_in_size);
|
||||
if (NULL == md->extra_in)
|
||||
abort ();
|
||||
memcpy (md->extra_in,
|
||||
extra_in,
|
||||
extra_in_size);
|
||||
}
|
||||
{
|
||||
md->extra_in = malloc (extra_in_size);
|
||||
if (NULL == md->extra_in)
|
||||
abort ();
|
||||
memcpy (md->extra_in,
|
||||
extra_in,
|
||||
extra_in_size);
|
||||
}
|
||||
md->extra_in_size = extra_in_size;
|
||||
md->sock = sock;
|
||||
md->urh = urh;
|
||||
@@ -252,20 +253,20 @@ ahc_echo (void *cls,
|
||||
static int aptr;
|
||||
struct MHD_Response *response;
|
||||
int ret;
|
||||
(void)cls; /* Unused. Silent compiler warning. */
|
||||
(void)url; /* Unused. Silent compiler warning. */
|
||||
(void)version; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data; /* Unused. Silent compiler warning. */
|
||||
(void)upload_data_size; /* Unused. Silent compiler warning. */
|
||||
(void) cls; /* Unused. Silent compiler warning. */
|
||||
(void) url; /* Unused. Silent compiler warning. */
|
||||
(void) version; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data; /* Unused. Silent compiler warning. */
|
||||
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
||||
|
||||
if (0 != strcmp (method, "GET"))
|
||||
return MHD_NO; /* unexpected method */
|
||||
if (&aptr != *ptr)
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
/* do never respond on first call */
|
||||
*ptr = &aptr;
|
||||
return MHD_YES;
|
||||
}
|
||||
*ptr = NULL; /* reset when done */
|
||||
response = MHD_create_response_for_upgrade (&uh_cb,
|
||||
NULL);
|
||||
@@ -288,11 +289,12 @@ main (int argc,
|
||||
struct MHD_Daemon *d;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_ALLOW_UPGRADE | MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
{
|
||||
printf ("%s PORT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
d = MHD_start_daemon (MHD_ALLOW_UPGRADE | MHD_USE_AUTO
|
||||
| MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
|
||||
atoi (argv[1]),
|
||||
NULL, NULL,
|
||||
&ahc_echo, NULL,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
enum MHD_Bool
|
||||
(*check_record_pending)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
enum MHD_Bool
|
||||
(*check_record_pending)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
|
||||
see:
|
||||
see:
|
||||
gnutls_record_check_pending (connection->tls_session)
|
||||
|
||||
+12
-12
@@ -1,15 +1,15 @@
|
||||
enum MHD_Bool
|
||||
(*handshake)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs):
|
||||
enum MHD_Bool
|
||||
(*handshake)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs) :
|
||||
|
||||
|
||||
|
||||
if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
|
||||
{ /* HTTPS connection. */
|
||||
if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
|
||||
{
|
||||
if (! MHD_run_tls_handshake_ (connection))
|
||||
return MHD_FALSE;
|
||||
}
|
||||
}
|
||||
return MHD_TRUE;
|
||||
if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
|
||||
{ /* HTTPS connection. */
|
||||
if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
|
||||
{
|
||||
if (! MHD_run_tls_handshake_ (connection))
|
||||
return MHD_FALSE;
|
||||
}
|
||||
}
|
||||
return MHD_TRUE;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
enum MHD_Bool
|
||||
(*idle_ready)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
enum MHD_Bool
|
||||
(*idle_ready)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
|
||||
|
||||
if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
|
||||
{ /* HTTPS connection. */
|
||||
if ((MHD_TLS_CONN_INIT <= connection->tls_state) &&
|
||||
(MHD_TLS_CONN_CONNECTED > connection->tls_state))
|
||||
return false;
|
||||
}
|
||||
if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
|
||||
{ /* HTTPS connection. */
|
||||
if ((MHD_TLS_CONN_INIT <= connection->tls_state) &&
|
||||
(MHD_TLS_CONN_CONNECTED > connection->tls_state))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
+20
-18
@@ -40,12 +40,12 @@ gcry_w32_mutex_init (void **ppmtx)
|
||||
|
||||
if (NULL == *ppmtx)
|
||||
return ENOMEM;
|
||||
if (! MHD_mutex_init_ ((MHD_mutex_*)*ppmtx))
|
||||
{
|
||||
free (*ppmtx);
|
||||
*ppmtx = NULL;
|
||||
return EPERM;
|
||||
}
|
||||
if (! MHD_mutex_init_ ((MHD_mutex_*) *ppmtx))
|
||||
{
|
||||
free (*ppmtx);
|
||||
*ppmtx = NULL;
|
||||
return EPERM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ gcry_w32_mutex_init (void **ppmtx)
|
||||
static int
|
||||
gcry_w32_mutex_destroy (void **ppmtx)
|
||||
{
|
||||
int res = (MHD_mutex_destroy_ ((MHD_mutex_*)*ppmtx)) ? 0 : EINVAL;
|
||||
int res = (MHD_mutex_destroy_ ((MHD_mutex_*) *ppmtx)) ? 0 : EINVAL;
|
||||
free (*ppmtx);
|
||||
return res;
|
||||
}
|
||||
@@ -62,14 +62,14 @@ gcry_w32_mutex_destroy (void **ppmtx)
|
||||
static int
|
||||
gcry_w32_mutex_lock (void **ppmtx)
|
||||
{
|
||||
return MHD_mutex_lock_ ((MHD_mutex_*)*ppmtx) ? 0 : EINVAL;
|
||||
return MHD_mutex_lock_ ((MHD_mutex_*) *ppmtx) ? 0 : EINVAL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
gcry_w32_mutex_unlock (void **ppmtx)
|
||||
{
|
||||
return MHD_mutex_unlock_ ((MHD_mutex_*)*ppmtx) ? 0 : EINVAL;
|
||||
return MHD_mutex_unlock_ ((MHD_mutex_*) *ppmtx) ? 0 : EINVAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,8 @@ static struct gcry_thread_cbs gcry_threads_w32 = {
|
||||
(GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
|
||||
NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
|
||||
gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
#endif /* defined(MHD_W32_MUTEX_) */
|
||||
#endif /* HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 */
|
||||
@@ -94,7 +95,7 @@ volatile int global_init_count = 0;
|
||||
/**
|
||||
* Global initialisation mutex
|
||||
*/
|
||||
MHD_MUTEX_STATIC_DEFN_INIT_(global_init_mutex_);
|
||||
MHD_MUTEX_STATIC_DEFN_INIT_ (global_init_mutex_);
|
||||
#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
|
||||
|
||||
#endif
|
||||
@@ -108,12 +109,12 @@ void
|
||||
MHD_TLS_check_global_init_ (void)
|
||||
{
|
||||
#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
|
||||
MHD_mutex_lock_chk_(&global_init_mutex_);
|
||||
MHD_mutex_lock_chk_ (&global_init_mutex_);
|
||||
#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
|
||||
if (0 == global_init_count++)
|
||||
MHD_init ();
|
||||
#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
|
||||
MHD_mutex_unlock_chk_(&global_init_mutex_);
|
||||
MHD_mutex_unlock_chk_ (&global_init_mutex_);
|
||||
#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
|
||||
}
|
||||
|
||||
@@ -133,16 +134,17 @@ MHD_TLS_init (void)
|
||||
#if defined(MHD_USE_POSIX_THREADS)
|
||||
if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
|
||||
&gcry_threads_pthread))
|
||||
MHD_PANIC (_("Failed to initialise multithreading in libgcrypt\n"));
|
||||
MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt\n"));
|
||||
#elif defined(MHD_W32_MUTEX_)
|
||||
if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
|
||||
&gcry_threads_w32))
|
||||
MHD_PANIC (_("Failed to initialise multithreading in libgcrypt\n"));
|
||||
MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt\n"));
|
||||
#endif /* defined(MHD_W32_MUTEX_) */
|
||||
gcry_check_version (NULL);
|
||||
#else
|
||||
if (NULL == gcry_check_version ("1.6.0"))
|
||||
MHD_PANIC (_("libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n"));
|
||||
MHD_PANIC (_ (
|
||||
"libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n"));
|
||||
#endif
|
||||
#endif /* MHD_HTTPS_REQUIRE_GRYPT */
|
||||
gnutls_global_init ();
|
||||
@@ -150,11 +152,11 @@ MHD_TLS_init (void)
|
||||
|
||||
|
||||
void
|
||||
MHD_TLS_fini(void)
|
||||
MHD_TLS_fini (void)
|
||||
{
|
||||
gnutls_global_deinit ();
|
||||
}
|
||||
|
||||
#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
|
||||
_SET_INIT_AND_DEINIT_FUNCS(MHD_TLS_init, MHD_TLS_fini);
|
||||
_SET_INIT_AND_DEINIT_FUNCS (MHD_TLS_init, MHD_TLS_fini);
|
||||
#endif /* _AUTOINIT_FUNCS_ARE_SUPPORTED */
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
* Do nothing - global initialisation is
|
||||
* performed by library constructor.
|
||||
*/
|
||||
#define MHD_TLS_check_global_init_() (void)0
|
||||
#define MHD_TLS_check_global_init_() (void) 0
|
||||
#else /* ! _AUTOINIT_FUNCS_ARE_SUPPORTED */
|
||||
/**
|
||||
* Check whether global initialisation was performed
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
recv:
|
||||
recv :
|
||||
|
||||
res = gnutls_record_recv (connection->tls_session,
|
||||
&urh->in_buffer[urh->in_buffer_used],
|
||||
buf_size);
|
||||
&urh->in_buffer[urh->in_buffer_used],
|
||||
buf_size);
|
||||
|
||||
+8
-8
@@ -1,11 +1,11 @@
|
||||
ssize_t
|
||||
(*send)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs,
|
||||
const void *buf,
|
||||
size_t buf_size);
|
||||
ssize_t
|
||||
(*send)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs,
|
||||
const void *buf,
|
||||
size_t buf_size);
|
||||
|
||||
|
||||
see:
|
||||
res = gnutls_record_send (connection->tls_session,
|
||||
urh->out_buffer,
|
||||
data_size);
|
||||
res = gnutls_record_send (connection->tls_session,
|
||||
urh->out_buffer,
|
||||
data_size);
|
||||
|
||||
@@ -1,57 +1,58 @@
|
||||
|
||||
|
||||
setup_connection ()
|
||||
{
|
||||
connection->tls_state = MHD_TLS_CONN_INIT;
|
||||
MHD_set_https_callbacks (connection);
|
||||
gnutls_init (&connection->tls_session,
|
||||
GNUTLS_SERVER
|
||||
#if (GNUTLS_VERSION_NUMBER+0 >= 0x030402)
|
||||
| GNUTLS_NO_SIGNAL
|
||||
connection->tls_state = MHD_TLS_CONN_INIT;
|
||||
MHD_set_https_callbacks (connection);
|
||||
gnutls_init (&connection->tls_session,
|
||||
GNUTLS_SERVER
|
||||
#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030402)
|
||||
| GNUTLS_NO_SIGNAL
|
||||
#endif /* GNUTLS_VERSION_NUMBER >= 0x030402 */
|
||||
#if GNUTLS_VERSION_MAJOR >= 3
|
||||
| GNUTLS_NONBLOCK
|
||||
| GNUTLS_NONBLOCK
|
||||
#endif /* GNUTLS_VERSION_MAJOR >= 3*/
|
||||
);
|
||||
gnutls_priority_set (connection->tls_session,
|
||||
daemon->priority_cache);
|
||||
switch (daemon->cred_type)
|
||||
{
|
||||
/* set needed credentials for certificate authentication. */
|
||||
case GNUTLS_CRD_CERTIFICATE:
|
||||
gnutls_credentials_set (connection->tls_session,
|
||||
GNUTLS_CRD_CERTIFICATE,
|
||||
daemon->x509_cred);
|
||||
break;
|
||||
default:
|
||||
);
|
||||
gnutls_priority_set (connection->tls_session,
|
||||
daemon->priority_cache);
|
||||
switch (daemon->cred_type)
|
||||
{
|
||||
/* set needed credentials for certificate authentication. */
|
||||
case GNUTLS_CRD_CERTIFICATE:
|
||||
gnutls_credentials_set (connection->tls_session,
|
||||
GNUTLS_CRD_CERTIFICATE,
|
||||
daemon->x509_cred);
|
||||
break;
|
||||
default:
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (connection->daemon,
|
||||
_("Failed to setup TLS credentials: unknown credential type %d\n"),
|
||||
daemon->cred_type);
|
||||
MHD_DLOG (connection->daemon,
|
||||
_ (
|
||||
"Failed to setup TLS credentials: unknown credential type %d\n"),
|
||||
daemon->cred_type);
|
||||
#endif
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
MHD_ip_limit_del (daemon,
|
||||
addr,
|
||||
addrlen);
|
||||
free (connection);
|
||||
MHD_PANIC (_("Unknown credential type"));
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
MHD_ip_limit_del (daemon,
|
||||
addr,
|
||||
addrlen);
|
||||
free (connection);
|
||||
MHD_PANIC (_ ("Unknown credential type"));
|
||||
#if EINVAL
|
||||
errno = EINVAL;
|
||||
errno = EINVAL;
|
||||
#endif
|
||||
return MHD_NO;
|
||||
}
|
||||
#if (GNUTLS_VERSION_NUMBER+0 >= 0x030109) && !defined(_WIN64)
|
||||
gnutls_transport_set_int (connection->tls_session, (int)(client_socket));
|
||||
return MHD_NO;
|
||||
}
|
||||
#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030109) && ! defined(_WIN64)
|
||||
gnutls_transport_set_int (connection->tls_session, (int) (client_socket));
|
||||
#else /* GnuTLS before 3.1.9 or Win x64 */
|
||||
gnutls_transport_set_ptr (connection->tls_session, (gnutls_transport_ptr_t)(intptr_t)(client_socket));
|
||||
gnutls_transport_set_ptr (connection->tls_session,
|
||||
(gnutls_transport_ptr_t) (intptr_t) (client_socket));
|
||||
#endif /* GnuTLS before 3.1.9 */
|
||||
#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
|
||||
gnutls_transport_set_push_function (connection->tls_session, MHD_tls_push_func_);
|
||||
gnutls_transport_set_push_function (connection->tls_session,
|
||||
MHD_tls_push_func_);
|
||||
#endif /* MHD_TLSLIB_NEED_PUSH_FUNC */
|
||||
if (daemon->https_mem_trust)
|
||||
gnutls_certificate_server_set_request (connection->tls_session,
|
||||
GNUTLS_CERT_REQUEST);
|
||||
if (daemon->https_mem_trust)
|
||||
gnutls_certificate_server_set_request (connection->tls_session,
|
||||
GNUTLS_CERT_REQUEST);
|
||||
#else /* ! HTTPS_SUPPORT */
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
enum MHD_Bool
|
||||
(*shutdown_connection) (void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
enum MHD_Bool
|
||||
(*shutdown_connection)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
|
||||
see: MHD_tls_connection_shutdown()
|
||||
see: MHD_tls_connection_shutdown ()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const char *
|
||||
(*strerror)(void *cls,
|
||||
int ec);
|
||||
const char *
|
||||
(*strerror)(void *cls,
|
||||
int ec);
|
||||
|
||||
see:
|
||||
gnutls_strerror (ec));
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
enum MHD_Bool
|
||||
(*update_event_loop_info)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs,
|
||||
enum MHD_RequestEventLoopInfo *eli);
|
||||
enum MHD_Bool
|
||||
(*update_event_loop_info)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs,
|
||||
enum MHD_RequestEventLoopInfo *eli);
|
||||
|
||||
|
||||
switch (connection->tls_state)
|
||||
{
|
||||
case MHD_TLS_CONN_INIT:
|
||||
*eli = MHD_EVENT_LOOP_INFO_READ;
|
||||
return true;
|
||||
case MHD_TLS_CONN_HANDSHAKING:
|
||||
if (0 == gnutls_record_get_direction (connection->tls_session))
|
||||
*eli = MHD_EVENT_LOOP_INFO_READ;
|
||||
else
|
||||
*eli = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch (connection->tls_state)
|
||||
{
|
||||
case MHD_TLS_CONN_INIT:
|
||||
*eli = MHD_EVENT_LOOP_INFO_READ;
|
||||
return true;
|
||||
case MHD_TLS_CONN_HANDSHAKING:
|
||||
if (0 == gnutls_record_get_direction (connection->tls_session))
|
||||
*eli = MHD_EVENT_LOOP_INFO_READ;
|
||||
else
|
||||
*eli = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
/*
|
||||
General usage is simple: include this header, declare or define two
|
||||
functions with zero parameters (void) and any return type: one for
|
||||
initialization and one for deinitialization, add
|
||||
initialization and one for deinitialization, add
|
||||
_SET_INIT_AND_DEINIT_FUNCS(FuncInitName, FuncDeInitName) to the code
|
||||
and functions will be automatically called during application startup
|
||||
and shutdown.
|
||||
@@ -70,9 +70,9 @@
|
||||
#define AUTOINIT_FUNCS_VERSION 0x01000100
|
||||
|
||||
#if defined(__GNUC__)
|
||||
/* if possible - check for supported attribute */
|
||||
/* if possible - check for supported attribute */
|
||||
#ifdef __has_attribute
|
||||
#if !__has_attribute(constructor) || !__has_attribute(destructor)
|
||||
#if ! __has_attribute (constructor) || ! __has_attribute (destructor)
|
||||
#define _GNUC_ATTR_CONSTR_NOT_SUPPORTED 1
|
||||
#endif /* !__has_attribute(constructor) || !__has_attribute(destructor) */
|
||||
#endif /* __has_attribute */
|
||||
@@ -80,20 +80,20 @@
|
||||
|
||||
/* "_attribute__ ((constructor))" is supported by GCC, clang and
|
||||
Sun/Oracle compiler starting from version 12.1. */
|
||||
#if (defined(__GNUC__) && !defined(_GNUC_ATTR_CONSTR_NOT_SUPPORTED)) || \
|
||||
(defined(__SUNPRO_C) && __SUNPRO_C+0 >= 0x5100)
|
||||
#if (defined(__GNUC__) && ! defined(_GNUC_ATTR_CONSTR_NOT_SUPPORTED)) || \
|
||||
(defined(__SUNPRO_C) && __SUNPRO_C + 0 >= 0x5100)
|
||||
|
||||
#define GNUC_SET_INIT_AND_DEINIT(FI,FD) \
|
||||
void __attribute__ ((constructor)) _GNUC_init_helper_##FI(void) \
|
||||
{ (void)(FI)(); } \
|
||||
void __attribute__ ((destructor)) _GNUC_deinit_helper_##FD(void) \
|
||||
{ (void)(FD)(); } \
|
||||
struct _GNUC_dummy_str_##FI{int i;}
|
||||
void __attribute__ ((constructor)) _GNUC_init_helper_ ## FI (void) \
|
||||
{ (void) (FI) (); } \
|
||||
void __attribute__ ((destructor)) _GNUC_deinit_helper_ ## FD (void) \
|
||||
{ (void) (FD) (); } \
|
||||
struct _GNUC_dummy_str_ ## FI {int i;}
|
||||
|
||||
#define _SET_INIT_AND_DEINIT_FUNCS(FI,FD) GNUC_SET_INIT_AND_DEINIT(FI,FD)
|
||||
#define _SET_INIT_AND_DEINIT_FUNCS(FI,FD) GNUC_SET_INIT_AND_DEINIT (FI,FD)
|
||||
#define _AUTOINIT_FUNCS_ARE_SUPPORTED 1
|
||||
|
||||
#elif defined (_MSC_FULL_VER) && _MSC_VER+0 >= 1600
|
||||
#elif defined (_MSC_FULL_VER) && _MSC_VER + 0 >= 1600
|
||||
|
||||
/* Make sure that your project/sources define:
|
||||
_LIB if building a static library (_LIB is ignored if _CONSOLE is defined);
|
||||
@@ -107,9 +107,9 @@
|
||||
|
||||
/* Stringify macros */
|
||||
#define _INSTRMACRO(a) #a
|
||||
#define _STRMACRO(a) _INSTRMACRO(a)
|
||||
#define _STRMACRO(a) _INSTRMACRO (a)
|
||||
|
||||
#if !defined(_USRDLL) || defined(AUTOINIT_FUNCS_DECLARE_STATIC_REG)
|
||||
#if ! defined(_USRDLL) || defined(AUTOINIT_FUNCS_DECLARE_STATIC_REG)
|
||||
|
||||
/* required for atexit() */
|
||||
#include <stdlib.h>
|
||||
@@ -128,15 +128,16 @@
|
||||
#define W32_VARDECORPEFIXSTR ""
|
||||
#elif defined(_M_IX86) || defined(_X86_)
|
||||
#define W32_VARDECORPREFIX _
|
||||
#define W32_DECORVARNAME(v) _##v
|
||||
#define W32_DECORVARNAME(v) _ ## v
|
||||
#define W32_VARDECORPEFIXSTR "_"
|
||||
#else
|
||||
#error Do not know how to decorate symbols for this architecture
|
||||
#endif
|
||||
|
||||
/* Internal variable prefix (can be any) */
|
||||
#define W32_INITHELPERVARNAME(f) _initHelperDummy_##f
|
||||
#define W32_INITHELPERVARNAMEDECORSTR(f) W32_VARDECORPEFIXSTR _STRMACRO(W32_INITHELPERVARNAME(f))
|
||||
#define W32_INITHELPERVARNAME(f) _initHelperDummy_ ## f
|
||||
#define W32_INITHELPERVARNAMEDECORSTR(f) W32_VARDECORPEFIXSTR _STRMACRO ( \
|
||||
W32_INITHELPERVARNAME (f))
|
||||
|
||||
/* Declare section (segment), put variable pointing to init function to chosen segment,
|
||||
force linker to include variable to avoid omitting by optimizer */
|
||||
@@ -145,9 +146,10 @@
|
||||
/* Return value is ignored for C++ initializers */
|
||||
/* For C initializers: startup process is aborted if initializer return non-zero */
|
||||
#define W32_FPTR_IN_SEG(S,F) \
|
||||
__pragma(section(S,long,read)) \
|
||||
__pragma(comment(linker, "/INCLUDE:" W32_INITHELPERVARNAMEDECORSTR(F))) \
|
||||
W32_INITVARDECL __declspec(allocate(S)) int(__cdecl *W32_INITHELPERVARNAME(F))(void) = &F
|
||||
__pragma (section (S,long,read)) \
|
||||
__pragma (comment (linker, "/INCLUDE:" W32_INITHELPERVARNAMEDECORSTR (F))) \
|
||||
W32_INITVARDECL __declspec(allocate (S))int (__cdecl * W32_INITHELPERVARNAME ( \
|
||||
F))(void) = &F
|
||||
|
||||
/* Section (segment) names for pointers to initializers */
|
||||
#define W32_SEG_INIT_C_USER ".CRT$XCU"
|
||||
@@ -161,10 +163,10 @@
|
||||
during application startup */
|
||||
/* "lib" initializers are called before "user" initializers */
|
||||
/* "C" initializers are called before "C++" initializers */
|
||||
#define W32_REG_INIT_C_USER(F) W32_FPTR_IN_SEG(W32_SEG_INIT_C_USER,F)
|
||||
#define W32_REG_INIT_C_LIB(F) W32_FPTR_IN_SEG(W32_SEG_INIT_C_LIB,F)
|
||||
#define W32_REG_INIT_CXX_USER(F) W32_FPTR_IN_SEG(W32_SEG_INIT_CXX_USER,F)
|
||||
#define W32_REG_INIT_CXX_LIB(F) W32_FPTR_IN_SEG(W32_SEG_INIT_CXX_LIB,F)
|
||||
#define W32_REG_INIT_C_USER(F) W32_FPTR_IN_SEG (W32_SEG_INIT_C_USER,F)
|
||||
#define W32_REG_INIT_C_LIB(F) W32_FPTR_IN_SEG (W32_SEG_INIT_C_LIB,F)
|
||||
#define W32_REG_INIT_CXX_USER(F) W32_FPTR_IN_SEG (W32_SEG_INIT_CXX_USER,F)
|
||||
#define W32_REG_INIT_CXX_LIB(F) W32_FPTR_IN_SEG (W32_SEG_INIT_CXX_LIB,F)
|
||||
|
||||
/* Choose main register macro based on language and program type */
|
||||
/* Assuming that _LIB or _USRDLL is defined for static or DLL-library */
|
||||
@@ -174,16 +176,18 @@
|
||||
/* Define AUTOINIT_FUNCS_FORCE_USER_LVL_INIT to register initializers
|
||||
at user level even if building library */
|
||||
#ifdef __cplusplus
|
||||
#if ((defined(_LIB) && !defined(_CONSOLE)) || defined(_USRDLL)) && !defined(AUTOINIT_FUNCS_FORCE_USER_LVL_INIT)
|
||||
#define W32_REGISTER_INIT(F) W32_REG_INIT_CXX_LIB(F)
|
||||
#if ((defined(_LIB) && ! defined(_CONSOLE)) || defined(_USRDLL)) && \
|
||||
! defined(AUTOINIT_FUNCS_FORCE_USER_LVL_INIT)
|
||||
#define W32_REGISTER_INIT(F) W32_REG_INIT_CXX_LIB (F)
|
||||
#else /* ! _LIB && ! _DLL */
|
||||
#define W32_REGISTER_INIT(F) W32_REG_INIT_CXX_USER(F)
|
||||
#define W32_REGISTER_INIT(F) W32_REG_INIT_CXX_USER (F)
|
||||
#endif /* ! _LIB && ! _DLL */
|
||||
#else /* !__cplusplus*/
|
||||
#if ((defined(_LIB) && !defined(_CONSOLE)) || defined(_USRDLL)) && !defined(AUTOINIT_FUNCS_FORCE_USER_LVL_INIT)
|
||||
#define W32_REGISTER_INIT(F) W32_REG_INIT_C_LIB(F)
|
||||
#if ((defined(_LIB) && ! defined(_CONSOLE)) || defined(_USRDLL)) && \
|
||||
! defined(AUTOINIT_FUNCS_FORCE_USER_LVL_INIT)
|
||||
#define W32_REGISTER_INIT(F) W32_REG_INIT_C_LIB (F)
|
||||
#else /* ! _LIB && ! _DLL */
|
||||
#define W32_REGISTER_INIT(F) W32_REG_INIT_C_USER(F)
|
||||
#define W32_REGISTER_INIT(F) W32_REG_INIT_C_USER (F)
|
||||
#endif /* ! _LIB && ! _DLL */
|
||||
#endif /* !__cplusplus*/
|
||||
|
||||
@@ -197,36 +201,36 @@
|
||||
#endif /* _USRDLL */
|
||||
|
||||
|
||||
#if !defined(_USRDLL) || defined(AUTOINIT_FUNCS_FORCE_STATIC_REG)
|
||||
#if ! defined(_USRDLL) || defined(AUTOINIT_FUNCS_FORCE_STATIC_REG)
|
||||
#define W32_SET_INIT_AND_DEINIT(FI,FD) \
|
||||
void __cdecl _W32_deinit_helper_##FD(void) \
|
||||
{ (void)(FD)(); } \
|
||||
int __cdecl _W32_init_helper_##FI(void) \
|
||||
{ (void)(FI)(); atexit(_W32_deinit_helper_##FD); return 0; } \
|
||||
W32_REGISTER_INIT(_W32_init_helper_##FI)
|
||||
void __cdecl _W32_deinit_helper_ ## FD (void) \
|
||||
{ (void) (FD) (); } \
|
||||
int __cdecl _W32_init_helper_ ## FI (void) \
|
||||
{ (void) (FI) (); atexit (_W32_deinit_helper_ ## FD); return 0; } \
|
||||
W32_REGISTER_INIT (_W32_init_helper_ ## FI)
|
||||
#else /* _USRDLL */
|
||||
|
||||
/* If DllMain is already present in code, define AUTOINIT_FUNCS_CALL_USR_DLLMAIN
|
||||
/* If DllMain is already present in code, define AUTOINIT_FUNCS_CALL_USR_DLLMAIN
|
||||
and rename DllMain to usr_DllMain */
|
||||
#ifndef AUTOINIT_FUNCS_CALL_USR_DLLMAIN
|
||||
#define W32_SET_INIT_AND_DEINIT(FI,FD) \
|
||||
BOOL WINAPI DllMain(HINSTANCE hinst,DWORD reason,LPVOID unused) \
|
||||
{ if(DLL_PROCESS_ATTACH==reason) {(void)(FI)();} \
|
||||
else if(DLL_PROCESS_DETACH==reason) {(void)(FD)();} \
|
||||
return TRUE; \
|
||||
} struct _W32_dummy_strc_##FI{int i;}
|
||||
BOOL WINAPI DllMain (HINSTANCE hinst,DWORD reason,LPVOID unused) \
|
||||
{ if (DLL_PROCESS_ATTACH==reason) {(void) (FI) ();} \
|
||||
else if (DLL_PROCESS_DETACH==reason) {(void) (FD) ();} \
|
||||
return TRUE; \
|
||||
} struct _W32_dummy_strc_ ## FI {int i;}
|
||||
#else /* AUTOINIT_FUNCS_CALL_USR_DLLMAIN */
|
||||
#define W32_SET_INIT_AND_DEINIT(FI,FD) \
|
||||
BOOL WINAPI usr_DllMain(HINSTANCE hinst,DWORD reason,LPVOID unused); \
|
||||
BOOL WINAPI DllMain(HINSTANCE hinst,DWORD reason,LPVOID unused) \
|
||||
{ if(DLL_PROCESS_ATTACH==reason) {(void)(FI)();} \
|
||||
else if(DLL_PROCESS_DETACH==reason) {(void)(FD)();} \
|
||||
return usr_DllMain(hinst,reason,unused); \
|
||||
} struct _W32_dummy_strc_##FI{int i;}
|
||||
BOOL WINAPI usr_DllMain (HINSTANCE hinst,DWORD reason,LPVOID unused); \
|
||||
BOOL WINAPI DllMain (HINSTANCE hinst,DWORD reason,LPVOID unused) \
|
||||
{ if (DLL_PROCESS_ATTACH==reason) {(void) (FI) ();} \
|
||||
else if (DLL_PROCESS_DETACH==reason) {(void) (FD) ();} \
|
||||
return usr_DllMain (hinst,reason,unused); \
|
||||
} struct _W32_dummy_strc_ ## FI {int i;}
|
||||
#endif /* AUTOINIT_FUNCS_CALL_USR_DLLMAIN */
|
||||
#endif /* _USRDLL */
|
||||
|
||||
#define _SET_INIT_AND_DEINIT_FUNCS(FI,FD) W32_SET_INIT_AND_DEINIT(FI,FD)
|
||||
#define _SET_INIT_AND_DEINIT_FUNCS(FI,FD) W32_SET_INIT_AND_DEINIT (FI,FD)
|
||||
/* Indicate that automatic initializers/deinitializers are supported */
|
||||
#define _AUTOINIT_FUNCS_ARE_SUPPORTED 1
|
||||
|
||||
@@ -235,7 +239,8 @@
|
||||
/* Define EMIT_ERROR_IF_AUTOINIT_FUNCS_ARE_NOT_SUPPORTED before inclusion of header to
|
||||
abort compilation if automatic initializers/deinitializers are not supported */
|
||||
#ifdef EMIT_ERROR_IF_AUTOINIT_FUNCS_ARE_NOT_SUPPORTED
|
||||
#error Compiler/platform don not support automatic calls of user-defined initializer and deinitializer
|
||||
#error \
|
||||
Compiler/platform don not support automatic calls of user-defined initializer and deinitializer
|
||||
#endif /* EMIT_ERROR_IF_AUTOINIT_FUNCS_ARE_NOT_SUPPORTED */
|
||||
|
||||
/* Do nothing */
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
#ifndef _MHD_EXTERN
|
||||
#if defined(BUILDING_MHD_LIB) && defined(_WIN32) && \
|
||||
(defined(DLL_EXPORT) || defined(MHD_W32DLL))
|
||||
(defined(DLL_EXPORT) || defined(MHD_W32DLL))
|
||||
#define _MHD_EXTERN __declspec(dllexport) extern
|
||||
#else /* !BUILDING_MHD_LIB || !_WIN32 || (!DLL_EXPORT && !MHD_W32DLL) */
|
||||
#define _MHD_EXTERN extern
|
||||
@@ -66,7 +66,7 @@
|
||||
#endif /* !FD_SETSIZE && !W32 */
|
||||
|
||||
#if defined(HAVE_LINUX_SENDFILE) || defined(HAVE_FREEBSD_SENDFILE) || \
|
||||
defined(HAVE_DARWIN_SENDFILE) || defined(HAVE_SOLARIS_SENDFILE)
|
||||
defined(HAVE_DARWIN_SENDFILE) || defined(HAVE_SOLARIS_SENDFILE)
|
||||
/* Have any supported sendfile() function. */
|
||||
#define _MHD_HAVE_SENDFILE
|
||||
#endif /* HAVE_LINUX_SENDFILE || HAVE_FREEBSD_SENDFILE ||
|
||||
@@ -104,7 +104,8 @@
|
||||
#define RESTRICT __restrict__
|
||||
#endif /* __VXWORKS__ || __vxworks || OS_VXWORKS */
|
||||
|
||||
#if LINUX+0 && (defined(HAVE_SENDFILE64) || defined(HAVE_LSEEK64)) && ! defined(_LARGEFILE64_SOURCE)
|
||||
#if LINUX + 0 && (defined(HAVE_SENDFILE64) || defined(HAVE_LSEEK64)) && \
|
||||
! defined(_LARGEFILE64_SOURCE)
|
||||
/* On Linux, special macro is required to enable definitions of some xxx64 functions */
|
||||
#define _LARGEFILE64_SOURCE 1
|
||||
#endif
|
||||
@@ -115,12 +116,13 @@
|
||||
#endif /* HAVE_C11_GMTIME_S */
|
||||
|
||||
#if defined(MHD_FAVOR_FAST_CODE) && defined(MHD_FAVOR_SMALL_CODE)
|
||||
#error MHD_FAVOR_FAST_CODE and MHD_FAVOR_SMALL_CODE are both defined. Cannot favor speed and size at the same time.
|
||||
#error \
|
||||
MHD_FAVOR_FAST_CODE and MHD_FAVOR_SMALL_CODE are both defined. Cannot favor speed and size at the same time.
|
||||
#endif /* MHD_FAVOR_FAST_CODE && MHD_FAVOR_SMALL_CODE */
|
||||
|
||||
/* Define MHD_FAVOR_FAST_CODE to force fast code path or
|
||||
define MHD_FAVOR_SMALL_CODE to choose compact code path */
|
||||
#if !defined(MHD_FAVOR_FAST_CODE) && !defined(MHD_FAVOR_SMALL_CODE)
|
||||
#if ! defined(MHD_FAVOR_FAST_CODE) && ! defined(MHD_FAVOR_SMALL_CODE)
|
||||
/* Try to detect user preferences */
|
||||
/* Defined by GCC and many compatible compilers */
|
||||
#if defined(__OPTIMIZE_SIZE__)
|
||||
@@ -130,7 +132,7 @@
|
||||
#endif /* __OPTIMIZE__ */
|
||||
#endif /* !MHD_FAVOR_FAST_CODE && !MHD_FAVOR_SMALL_CODE */
|
||||
|
||||
#if !defined(MHD_FAVOR_FAST_CODE) && !defined(MHD_FAVOR_SMALL_CODE)
|
||||
#if ! defined(MHD_FAVOR_FAST_CODE) && ! defined(MHD_FAVOR_SMALL_CODE)
|
||||
/* Use faster code by default */
|
||||
#define MHD_FAVOR_FAST_CODE 1
|
||||
#endif /* !MHD_FAVOR_FAST_CODE && !MHD_FAVOR_SMALL_CODE */
|
||||
|
||||
+217
-173
@@ -108,7 +108,7 @@ extern "C"
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
#if ! defined(_WIN32) || defined(__CYGWIN__)
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -116,14 +116,14 @@ extern "C"
|
||||
/* Declare POSIX-compatible names */
|
||||
#define _CRT_DECLARE_NONSTDC_NAMES 1
|
||||
#include <ws2tcpip.h>
|
||||
#if defined(_MSC_FULL_VER) && !defined (_SSIZE_T_DEFINED)
|
||||
#if defined(_MSC_FULL_VER) && ! defined (_SSIZE_T_DEFINED)
|
||||
#define _SSIZE_T_DEFINED
|
||||
typedef intptr_t ssize_t;
|
||||
#endif /* !_SSIZE_T_DEFINED */
|
||||
#endif /* _WIN32 && ! __CYGWIN__ */
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__) && !defined(_SYS_TYPES_FD_SET)
|
||||
#if defined(__CYGWIN__) && ! defined(_SYS_TYPES_FD_SET)
|
||||
/* Do not define __USE_W32_SOCKETS under Cygwin! */
|
||||
#error Cygwin with winsock fd_set is not supported
|
||||
#endif
|
||||
@@ -182,7 +182,7 @@ typedef intptr_t ssize_t;
|
||||
/**
|
||||
* MHD_socket is type for socket FDs
|
||||
*/
|
||||
#if !defined(_WIN32) || defined(_SYS_TYPES_FD_SET)
|
||||
#if ! defined(_WIN32) || defined(_SYS_TYPES_FD_SET)
|
||||
#define MHD_POSIX_SOCKETS 1
|
||||
typedef int MHD_socket;
|
||||
#define MHD_INVALID_SOCKET (-1)
|
||||
@@ -207,30 +207,35 @@ typedef SOCKET MHD_socket;
|
||||
#endif /* MHD_NO_DEPRECATION */
|
||||
|
||||
#ifndef _MHD_DEPR_MACRO
|
||||
#if defined(_MSC_FULL_VER) && _MSC_VER+0 >= 1500
|
||||
#if defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1500
|
||||
/* VS 2008 or later */
|
||||
/* Stringify macros */
|
||||
#define _MHD_INSTRMACRO(a) #a
|
||||
#define _MHD_STRMACRO(a) _MHD_INSTRMACRO(a)
|
||||
#define _MHD_STRMACRO(a) _MHD_INSTRMACRO (a)
|
||||
/* deprecation message */
|
||||
#define _MHD_DEPR_MACRO(msg) __pragma(message(__FILE__ "(" _MHD_STRMACRO(__LINE__)"): warning: " msg))
|
||||
#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO(msg)
|
||||
#define _MHD_DEPR_MACRO(msg) __pragma (message (__FILE__ "(" _MHD_STRMACRO ( \
|
||||
__LINE__) "): warning: " msg))
|
||||
#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO (msg)
|
||||
#elif defined(__clang__) || defined (__GNUC_PATCHLEVEL__)
|
||||
/* clang or GCC since 3.0 */
|
||||
#define _MHD_GCC_PRAG(x) _Pragma (#x)
|
||||
#if (defined(__clang__) && (__clang_major__+0 >= 5 || \
|
||||
(!defined(__apple_build_version__) && (__clang_major__+0 > 3 || (__clang_major__+0 == 3 && __clang_minor__ >= 3))))) || \
|
||||
__GNUC__+0 > 4 || (__GNUC__+0 == 4 && __GNUC_MINOR__+0 >= 8)
|
||||
#if (defined(__clang__) && (__clang_major__ + 0 >= 5 || \
|
||||
(! defined(__apple_build_version__) && \
|
||||
(__clang_major__ + 0 > 3 || (__clang_major__ + 0 == 3 && __clang_minor__ >= \
|
||||
3))))) || \
|
||||
__GNUC__ + 0 > 4 || (__GNUC__ + 0 == 4 && __GNUC_MINOR__ + 0 >= 8)
|
||||
/* clang >= 3.3 (or XCode's clang >= 5.0) or
|
||||
GCC >= 4.8 */
|
||||
#define _MHD_DEPR_MACRO(msg) _MHD_GCC_PRAG(GCC warning msg)
|
||||
#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO(msg)
|
||||
#define _MHD_DEPR_MACRO(msg) _MHD_GCC_PRAG (GCC warning msg)
|
||||
#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO (msg)
|
||||
#else /* older clang or GCC */
|
||||
/* clang < 3.3, XCode's clang < 5.0, 3.0 <= GCC < 4.8 */
|
||||
#define _MHD_DEPR_MACRO(msg) _MHD_GCC_PRAG(message msg)
|
||||
#if (defined(__clang__) && (__clang_major__+0 > 2 || (__clang_major__+0 == 2 && __clang_minor__ >= 9))) /* FIXME: clang >= 2.9, earlier versions not tested */
|
||||
#define _MHD_DEPR_MACRO(msg) _MHD_GCC_PRAG (message msg)
|
||||
#if (defined(__clang__) && (__clang_major__ + 0 > 2 || (__clang_major__ + 0 == \
|
||||
2 && __clang_minor__ >= \
|
||||
9))) /* FIXME: clang >= 2.9, earlier versions not tested */
|
||||
/* clang handles inline pragmas better than GCC */
|
||||
#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO(msg)
|
||||
#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO (msg)
|
||||
#endif /* clang >= 2.9 */
|
||||
#endif /* older clang or GCC */
|
||||
/* #elif defined(SOMEMACRO) */ /* add compiler-specific macros here if required */
|
||||
@@ -247,17 +252,19 @@ typedef SOCKET MHD_socket;
|
||||
#endif /* !_MHD_DEPR_IN_MACRO */
|
||||
|
||||
#ifndef _MHD_DEPR_FUNC
|
||||
#if defined(_MSC_FULL_VER) && _MSC_VER+0 >= 1400
|
||||
#if defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1400
|
||||
/* VS 2005 or later */
|
||||
#define _MHD_DEPR_FUNC(msg) __declspec(deprecated(msg))
|
||||
#elif defined(_MSC_FULL_VER) && _MSC_VER+0 >= 1310
|
||||
#define _MHD_DEPR_FUNC(msg) __declspec(deprecated (msg))
|
||||
#elif defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1310
|
||||
/* VS .NET 2003 deprecation do not support custom messages */
|
||||
#define _MHD_DEPR_FUNC(msg) __declspec(deprecated)
|
||||
#elif (__GNUC__+0 >= 5) || (defined (__clang__) && \
|
||||
(__clang_major__+0 > 2 || (__clang_major__+0 == 2 && __clang_minor__ >= 9))) /* FIXME: earlier versions not tested */
|
||||
#elif (__GNUC__ + 0 >= 5) || (defined (__clang__) && \
|
||||
(__clang_major__ + 0 > 2 || (__clang_major__ + 0 == 2 && __clang_minor__ >= \
|
||||
9))) /* FIXME: earlier versions not tested */
|
||||
/* GCC >= 5.0 or clang >= 2.9 */
|
||||
#define _MHD_DEPR_FUNC(msg) __attribute__((deprecated(msg)))
|
||||
#elif defined (__clang__) || __GNUC__+0 > 3 || (__GNUC__+0 == 3 && __GNUC_MINOR__+0 >= 1)
|
||||
#define _MHD_DEPR_FUNC(msg) __attribute__((deprecated (msg)))
|
||||
#elif defined (__clang__) || __GNUC__ + 0 > 3 || (__GNUC__ + 0 == 3 && \
|
||||
__GNUC_MINOR__ + 0 >= 1)
|
||||
/* 3.1 <= GCC < 5.0 or clang < 2.9 */
|
||||
/* old GCC-style deprecation do not support custom messages */
|
||||
#define _MHD_DEPR_FUNC(msg) __attribute__((__deprecated__))
|
||||
@@ -282,7 +289,8 @@ typedef SOCKET MHD_socket;
|
||||
#define MHD_LONG_LONG long long
|
||||
#define MHD_UNSIGNED_LONG_LONG unsigned long long
|
||||
#else /* MHD_LONG_LONG */
|
||||
_MHD_DEPR_MACRO("Macro MHD_LONG_LONG is deprecated, use MHD_UNSIGNED_LONG_LONG")
|
||||
_MHD_DEPR_MACRO (
|
||||
"Macro MHD_LONG_LONG is deprecated, use MHD_UNSIGNED_LONG_LONG")
|
||||
#endif
|
||||
/**
|
||||
* Format string for printing a variable of type #MHD_LONG_LONG.
|
||||
@@ -295,14 +303,15 @@ _MHD_DEPR_MACRO("Macro MHD_LONG_LONG is deprecated, use MHD_UNSIGNED_LONG_LONG")
|
||||
#define MHD_LONG_LONG_PRINTF "ll"
|
||||
#define MHD_UNSIGNED_LONG_LONG_PRINTF "%llu"
|
||||
#else /* MHD_LONG_LONG_PRINTF */
|
||||
_MHD_DEPR_MACRO("Macro MHD_LONG_LONG_PRINTF is deprecated, use MHD_UNSIGNED_LONG_LONG_PRINTF")
|
||||
_MHD_DEPR_MACRO (
|
||||
"Macro MHD_LONG_LONG_PRINTF is deprecated, use MHD_UNSIGNED_LONG_LONG_PRINTF")
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Length of the binary output of the MD5 hash function.
|
||||
*/
|
||||
#define MHD_MD5_DIGEST_SIZE 16
|
||||
#define MHD_MD5_DIGEST_SIZE 16
|
||||
|
||||
|
||||
/**
|
||||
@@ -463,27 +472,39 @@ _MHD_DEPR_MACRO("Macro MHD_LONG_LONG_PRINTF is deprecated, use MHD_UNSIGNED_LONG
|
||||
/* Deprecated codes */
|
||||
/** @deprecated */
|
||||
#define MHD_HTTP_METHOD_NOT_ACCEPTABLE \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_HTTP_METHOD_NOT_ACCEPTABLE is deprecated, use MHD_HTTP_NOT_ACCEPTABLE") 406
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_HTTP_METHOD_NOT_ACCEPTABLE is deprecated, use MHD_HTTP_NOT_ACCEPTABLE") \
|
||||
406
|
||||
|
||||
/** @deprecated */
|
||||
#define MHD_HTTP_REQUEST_ENTITY_TOO_LARGE \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_HTTP_REQUEST_ENTITY_TOO_LARGE is deprecated, use MHD_HTTP_PAYLOAD_TOO_LARGE") 413
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_HTTP_REQUEST_ENTITY_TOO_LARGE is deprecated, use MHD_HTTP_PAYLOAD_TOO_LARGE") \
|
||||
413
|
||||
|
||||
/** @deprecated */
|
||||
#define MHD_HTTP_REQUEST_URI_TOO_LONG \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_HTTP_REQUEST_URI_TOO_LONG is deprecated, use MHD_HTTP_URI_TOO_LONG") 414
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_HTTP_REQUEST_URI_TOO_LONG is deprecated, use MHD_HTTP_URI_TOO_LONG") \
|
||||
414
|
||||
|
||||
/** @deprecated */
|
||||
#define MHD_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE is deprecated, use MHD_HTTP_RANGE_NOT_SATISFIABLE") 416
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE is deprecated, use MHD_HTTP_RANGE_NOT_SATISFIABLE") \
|
||||
416
|
||||
|
||||
/** @deprecated */
|
||||
#define MHD_HTTP_UNORDERED_COLLECTION \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_HTTP_UNORDERED_COLLECTION is deprecated as it was removed from RFC") 425
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_HTTP_UNORDERED_COLLECTION is deprecated as it was removed from RFC") \
|
||||
425
|
||||
|
||||
/** @deprecated */
|
||||
#define MHD_HTTP_NO_RESPONSE \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_HTTP_NO_RESPONSE is deprecated as it is nginx internal code for logs only") 444
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_HTTP_NO_RESPONSE is deprecated as it is nginx internal code for logs only") \
|
||||
444
|
||||
|
||||
|
||||
/** @} */ /* end of group httpcode */
|
||||
@@ -504,7 +525,7 @@ MHD_get_reason_phrase_for (unsigned int code);
|
||||
* with the SHOUTcast "ICY" line instad of "HTTP".
|
||||
* @ingroup specialized
|
||||
*/
|
||||
#define MHD_ICY_FLAG ((uint32_t)(((uint32_t)1) << 31))
|
||||
#define MHD_ICY_FLAG ((uint32_t) (((uint32_t) 1) << 31))
|
||||
|
||||
/**
|
||||
* @defgroup headers HTTP headers
|
||||
@@ -712,7 +733,8 @@ MHD_get_reason_phrase_for (unsigned int code);
|
||||
/* Standard. RFC6638 */
|
||||
#define MHD_HTTP_HEADER_IF_SCHEDULE_TAG_MATCH "If-Schedule-Tag-Match"
|
||||
/* Standard. RFC8473 */
|
||||
#define MHD_HTTP_HEADER_INCLUDE_REFERRED_TOKEN_BINDING_ID "Include-Referred-Token-Binding-ID"
|
||||
#define MHD_HTTP_HEADER_INCLUDE_REFERRED_TOKEN_BINDING_ID \
|
||||
"Include-Referred-Token-Binding-ID"
|
||||
/* No category. RFC4229 */
|
||||
#define MHD_HTTP_HEADER_KEEP_ALIVE "Keep-Alive"
|
||||
/* No category. RFC4229 */
|
||||
@@ -776,7 +798,8 @@ MHD_get_reason_phrase_for (unsigned int code);
|
||||
/* Standard. RFC7469 */
|
||||
#define MHD_HTTP_HEADER_PUBLIC_KEY_PINS "Public-Key-Pins"
|
||||
/* Standard. RFC7469 */
|
||||
#define MHD_HTTP_HEADER_PUBLIC_KEY_PINS_REPORT_ONLY "Public-Key-Pins-Report-Only"
|
||||
#define MHD_HTTP_HEADER_PUBLIC_KEY_PINS_REPORT_ONLY \
|
||||
"Public-Key-Pins-Report-Only"
|
||||
/* No category. RFC4437 */
|
||||
#define MHD_HTTP_HEADER_REDIRECT_REF "Redirect-Ref"
|
||||
/* Standard. RFC8555, Section 6.5.1 */
|
||||
@@ -843,7 +866,8 @@ MHD_get_reason_phrase_for (unsigned int code);
|
||||
#define MHD_HTTP_HEADER_X_FRAME_OPTIONS "X-Frame-Options"
|
||||
|
||||
/* Some provisional headers. */
|
||||
#define MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN "Access-Control-Allow-Origin"
|
||||
#define MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN \
|
||||
"Access-Control-Allow-Origin"
|
||||
/** @} */ /* end of group headers */
|
||||
|
||||
/**
|
||||
@@ -954,7 +978,8 @@ MHD_get_reason_phrase_for (unsigned int code);
|
||||
* See also: http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4
|
||||
* @{
|
||||
*/
|
||||
#define MHD_HTTP_POST_ENCODING_FORM_URLENCODED "application/x-www-form-urlencoded"
|
||||
#define MHD_HTTP_POST_ENCODING_FORM_URLENCODED \
|
||||
"application/x-www-form-urlencoded"
|
||||
#define MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA "multipart/form-data"
|
||||
|
||||
/** @} */ /* end of group postenc */
|
||||
@@ -1031,7 +1056,7 @@ enum MHD_FLAG
|
||||
#if 0
|
||||
/* let's do this later once versions that define MHD_USE_TLS a more widely deployed. */
|
||||
#define MHD_USE_SSL \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_USE_SSL is deprecated, use MHD_USE_TLS") \
|
||||
_MHD_DEPR_IN_MACRO ("Value MHD_USE_SSL is deprecated, use MHD_USE_TLS") \
|
||||
MHD_USE_TLS
|
||||
#endif
|
||||
|
||||
@@ -1056,7 +1081,8 @@ enum MHD_FLAG
|
||||
MHD_USE_SELECT_INTERNALLY = 8,
|
||||
#if 0 /* Will be marked for real deprecation later. */
|
||||
#define MHD_USE_SELECT_INTERNALLY \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_USE_SELECT_INTERNALLY is deprecated, use MHD_USE_INTERNAL_POLLING_THREAD instead") \
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_USE_SELECT_INTERNALLY is deprecated, use MHD_USE_INTERNAL_POLLING_THREAD instead") \
|
||||
MHD_USE_INTERNAL_POLLING_THREAD
|
||||
#endif /* 0 */
|
||||
|
||||
@@ -1081,7 +1107,8 @@ enum MHD_FLAG
|
||||
MHD_USE_PEDANTIC_CHECKS = 32,
|
||||
#if 0 /* Will be marked for real deprecation later. */
|
||||
#define MHD_USE_PEDANTIC_CHECKS \
|
||||
_MHD_DEPR_IN_MACRO("Flag MHD_USE_PEDANTIC_CHECKS is deprecated, use option MHD_OPTION_STRICT_FOR_CLIENT instead") \
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Flag MHD_USE_PEDANTIC_CHECKS is deprecated, use option MHD_OPTION_STRICT_FOR_CLIENT instead") \
|
||||
32
|
||||
#endif /* 0 */
|
||||
|
||||
@@ -1105,7 +1132,8 @@ enum MHD_FLAG
|
||||
MHD_USE_POLL_INTERNALLY = MHD_USE_POLL | MHD_USE_INTERNAL_POLLING_THREAD,
|
||||
#if 0 /* Will be marked for real deprecation later. */
|
||||
#define MHD_USE_POLL_INTERNALLY \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_USE_POLL_INTERNALLY is deprecated, use MHD_USE_POLL_INTERNAL_THREAD instead") \
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_USE_POLL_INTERNALLY is deprecated, use MHD_USE_POLL_INTERNAL_THREAD instead") \
|
||||
MHD_USE_POLL_INTERNAL_THREAD
|
||||
#endif /* 0 */
|
||||
|
||||
@@ -1121,7 +1149,8 @@ enum MHD_FLAG
|
||||
MHD_SUPPRESS_DATE_NO_CLOCK = 128,
|
||||
#if 0 /* Will be marked for real deprecation later. */
|
||||
#define MHD_SUPPRESS_DATE_NO_CLOCK \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_SUPPRESS_DATE_NO_CLOCK is deprecated, use MHD_USE_SUPPRESS_DATE_NO_CLOCK instead") \
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_SUPPRESS_DATE_NO_CLOCK is deprecated, use MHD_USE_SUPPRESS_DATE_NO_CLOCK instead") \
|
||||
MHD_USE_SUPPRESS_DATE_NO_CLOCK
|
||||
#endif /* 0 */
|
||||
|
||||
@@ -1147,7 +1176,8 @@ enum MHD_FLAG
|
||||
MHD_USE_EPOLL_LINUX_ONLY = 512,
|
||||
#if 0 /* Will be marked for real deprecation later. */
|
||||
#define MHD_USE_EPOLL_LINUX_ONLY \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_USE_EPOLL_LINUX_ONLY is deprecated, use MHD_USE_EPOLL") \
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_USE_EPOLL_LINUX_ONLY is deprecated, use MHD_USE_EPOLL") \
|
||||
MHD_USE_EPOLL
|
||||
#endif /* 0 */
|
||||
|
||||
@@ -1157,19 +1187,23 @@ enum MHD_FLAG
|
||||
* platform without `epoll` support will cause #MHD_start_daemon to fail.
|
||||
* @sa ::MHD_FEATURE_EPOLL, #MHD_USE_EPOLL, #MHD_USE_INTERNAL_POLLING_THREAD
|
||||
*/
|
||||
MHD_USE_EPOLL_INTERNAL_THREAD = MHD_USE_EPOLL | MHD_USE_INTERNAL_POLLING_THREAD,
|
||||
MHD_USE_EPOLL_INTERNAL_THREAD = MHD_USE_EPOLL
|
||||
| MHD_USE_INTERNAL_POLLING_THREAD,
|
||||
|
||||
/** @deprecated */
|
||||
MHD_USE_EPOLL_INTERNALLY = MHD_USE_EPOLL | MHD_USE_INTERNAL_POLLING_THREAD,
|
||||
/** @deprecated */
|
||||
MHD_USE_EPOLL_INTERNALLY_LINUX_ONLY = MHD_USE_EPOLL | MHD_USE_INTERNAL_POLLING_THREAD,
|
||||
MHD_USE_EPOLL_INTERNALLY_LINUX_ONLY = MHD_USE_EPOLL
|
||||
| MHD_USE_INTERNAL_POLLING_THREAD,
|
||||
#if 0 /* Will be marked for real deprecation later. */
|
||||
#define MHD_USE_EPOLL_INTERNALLY \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_USE_EPOLL_INTERNALLY is deprecated, use MHD_USE_EPOLL_INTERNAL_THREAD") \
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_USE_EPOLL_INTERNALLY is deprecated, use MHD_USE_EPOLL_INTERNAL_THREAD") \
|
||||
MHD_USE_EPOLL_INTERNAL_THREAD
|
||||
/** @deprecated */
|
||||
#define MHD_USE_EPOLL_INTERNALLY_LINUX_ONLY \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_USE_EPOLL_INTERNALLY_LINUX_ONLY is deprecated, use MHD_USE_EPOLL_INTERNAL_THREAD") \
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_USE_EPOLL_INTERNALLY_LINUX_ONLY is deprecated, use MHD_USE_EPOLL_INTERNAL_THREAD") \
|
||||
MHD_USE_EPOLL_INTERNAL_THREAD
|
||||
#endif /* 0 */
|
||||
|
||||
@@ -1191,7 +1225,8 @@ enum MHD_FLAG
|
||||
MHD_USE_PIPE_FOR_SHUTDOWN = 1024,
|
||||
#if 0 /* Will be marked for real deprecation later. */
|
||||
#define MHD_USE_PIPE_FOR_SHUTDOWN \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_USE_PIPE_FOR_SHUTDOWN is deprecated, use MHD_USE_ITC") \
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_USE_PIPE_FOR_SHUTDOWN is deprecated, use MHD_USE_ITC") \
|
||||
MHD_USE_ITC
|
||||
#endif /* 0 */
|
||||
|
||||
@@ -1212,7 +1247,8 @@ enum MHD_FLAG
|
||||
MHD_USE_EPOLL_TURBO = 4096,
|
||||
#if 0 /* Will be marked for real deprecation later. */
|
||||
#define MHD_USE_EPOLL_TURBO \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_USE_EPOLL_TURBO is deprecated, use MHD_USE_TURBO") \
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_USE_EPOLL_TURBO is deprecated, use MHD_USE_TURBO") \
|
||||
MHD_USE_TURBO
|
||||
#endif /* 0 */
|
||||
|
||||
@@ -1226,7 +1262,8 @@ enum MHD_FLAG
|
||||
MHD_USE_SUSPEND_RESUME = 8192 | MHD_USE_ITC,
|
||||
#if 0 /* Will be marked for real deprecation later. */
|
||||
#define MHD_USE_SUSPEND_RESUME \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_USE_SUSPEND_RESUME is deprecated, use MHD_ALLOW_SUSPEND_RESUME instead") \
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_USE_SUSPEND_RESUME is deprecated, use MHD_ALLOW_SUSPEND_RESUME instead") \
|
||||
MHD_ALLOW_SUSPEND_RESUME
|
||||
#endif /* 0 */
|
||||
|
||||
@@ -1269,13 +1306,13 @@ enum MHD_FLAG
|
||||
* Flag set to enable post-handshake client authentication
|
||||
* (only useful in combination with #MHD_USE_TLS).
|
||||
*/
|
||||
MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT = 1U <<17,
|
||||
MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT = 1U << 17,
|
||||
|
||||
/**
|
||||
* Flag set to enable TLS 1.3 early data. This has
|
||||
* security implications, be VERY careful when using this.
|
||||
*/
|
||||
MHD_USE_INSECURE_TLS_EARLY_DATA = 1U <<18
|
||||
MHD_USE_INSECURE_TLS_EARLY_DATA = 1U << 18
|
||||
|
||||
};
|
||||
|
||||
@@ -1308,10 +1345,10 @@ typedef void
|
||||
*/
|
||||
typedef int
|
||||
(*MHD_PskServerCredentialsCallback)(void *cls,
|
||||
const struct MHD_Connection *connection,
|
||||
const char *username,
|
||||
void **psk,
|
||||
size_t *psk_size);
|
||||
const struct MHD_Connection *connection,
|
||||
const char *username,
|
||||
void **psk,
|
||||
size_t *psk_size);
|
||||
|
||||
/**
|
||||
* @brief MHD options.
|
||||
@@ -1654,7 +1691,7 @@ enum MHD_OPTION
|
||||
* followed by a argument of type `gnutls_certificate_retrieve_function3 *`.
|
||||
* This option provides an
|
||||
* alternative/extension to #MHD_OPTION_HTTPS_CERT_CALLBACK.
|
||||
* You must use this version if you want to use OCSP stapling.
|
||||
* You must use this version if you want to use OCSP stapling.
|
||||
* Using this option requires GnuTLS 3.6.3 or higher.
|
||||
*/
|
||||
MHD_OPTION_HTTPS_CERT_CALLBACK2 = 31
|
||||
@@ -1701,7 +1738,8 @@ enum MHD_ValueKind
|
||||
*/
|
||||
MHD_RESPONSE_HEADER_KIND = 0,
|
||||
#define MHD_RESPONSE_HEADER_KIND \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_RESPONSE_HEADER_KIND is deprecated and not used") \
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_RESPONSE_HEADER_KIND is deprecated and not used") \
|
||||
MHD_RESPONSE_HEADER_KIND
|
||||
|
||||
/**
|
||||
@@ -2197,11 +2235,11 @@ typedef int
|
||||
*/
|
||||
typedef int
|
||||
(*MHD_KeyValueIteratorN) (void *cls,
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
size_t key_size,
|
||||
const char *value,
|
||||
size_t value_size);
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
size_t key_size,
|
||||
const char *value,
|
||||
size_t value_size);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2323,10 +2361,10 @@ typedef int
|
||||
*/
|
||||
_MHD_EXTERN struct MHD_Daemon *
|
||||
MHD_start_daemon_va (unsigned int flags,
|
||||
uint16_t port,
|
||||
MHD_AcceptPolicyCallback apc, void *apc_cls,
|
||||
MHD_AccessHandlerCallback dh, void *dh_cls,
|
||||
va_list ap);
|
||||
uint16_t port,
|
||||
MHD_AcceptPolicyCallback apc, void *apc_cls,
|
||||
MHD_AccessHandlerCallback dh, void *dh_cls,
|
||||
va_list ap);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2351,10 +2389,10 @@ MHD_start_daemon_va (unsigned int flags,
|
||||
*/
|
||||
_MHD_EXTERN struct MHD_Daemon *
|
||||
MHD_start_daemon (unsigned int flags,
|
||||
uint16_t port,
|
||||
MHD_AcceptPolicyCallback apc, void *apc_cls,
|
||||
MHD_AccessHandlerCallback dh, void *dh_cls,
|
||||
...);
|
||||
uint16_t port,
|
||||
MHD_AcceptPolicyCallback apc, void *apc_cls,
|
||||
MHD_AccessHandlerCallback dh, void *dh_cls,
|
||||
...);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2419,9 +2457,9 @@ MHD_stop_daemon (struct MHD_Daemon *daemon);
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_add_connection (struct MHD_Daemon *daemon,
|
||||
MHD_socket client_socket,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen);
|
||||
MHD_socket client_socket,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2457,8 +2495,8 @@ _MHD_EXTERN int
|
||||
MHD_get_fdset (struct MHD_Daemon *daemon,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *except_fd_set,
|
||||
MHD_socket *max_fd);
|
||||
fd_set *except_fd_set,
|
||||
MHD_socket *max_fd);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2495,11 +2533,11 @@ MHD_get_fdset (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_get_fdset2 (struct MHD_Daemon *daemon,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *except_fd_set,
|
||||
MHD_socket *max_fd,
|
||||
unsigned int fd_setsize);
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *except_fd_set,
|
||||
MHD_socket *max_fd,
|
||||
unsigned int fd_setsize);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2527,7 +2565,8 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon,
|
||||
* @ingroup event
|
||||
*/
|
||||
#define MHD_get_fdset(daemon,read_fd_set,write_fd_set,except_fd_set,max_fd) \
|
||||
MHD_get_fdset2((daemon),(read_fd_set),(write_fd_set),(except_fd_set),(max_fd),FD_SETSIZE)
|
||||
MHD_get_fdset2 ((daemon),(read_fd_set),(write_fd_set),(except_fd_set), \
|
||||
(max_fd),FD_SETSIZE)
|
||||
|
||||
|
||||
/**
|
||||
@@ -2550,7 +2589,7 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_get_timeout (struct MHD_Daemon *daemon,
|
||||
MHD_UNSIGNED_LONG_LONG *timeout);
|
||||
MHD_UNSIGNED_LONG_LONG *timeout);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2601,9 +2640,9 @@ MHD_run (struct MHD_Daemon *daemon);
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_run_from_select (struct MHD_Daemon *daemon,
|
||||
const fd_set *read_fd_set,
|
||||
const fd_set *write_fd_set,
|
||||
const fd_set *except_fd_set);
|
||||
const fd_set *read_fd_set,
|
||||
const fd_set *write_fd_set,
|
||||
const fd_set *except_fd_set);
|
||||
|
||||
|
||||
|
||||
@@ -2678,7 +2717,7 @@ _MHD_EXTERN int
|
||||
MHD_set_connection_value (struct MHD_Connection *connection,
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
const char *value);
|
||||
const char *value);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2708,11 +2747,11 @@ MHD_set_connection_value (struct MHD_Connection *connection,
|
||||
*/
|
||||
int
|
||||
MHD_set_connection_value_n (struct MHD_Connection *connection,
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
size_t key_size,
|
||||
const char *value,
|
||||
size_t value_size);
|
||||
const char *value,
|
||||
size_t value_size);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2760,8 +2799,8 @@ MHD_http_unescape (char *val);
|
||||
*/
|
||||
_MHD_EXTERN const char *
|
||||
MHD_lookup_connection_value (struct MHD_Connection *connection,
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key);
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2806,7 +2845,7 @@ MHD_lookup_connection_value_n (struct MHD_Connection *connection,
|
||||
_MHD_EXTERN int
|
||||
MHD_queue_response (struct MHD_Connection *connection,
|
||||
unsigned int status_code,
|
||||
struct MHD_Response *response);
|
||||
struct MHD_Response *response);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2934,9 +2973,9 @@ MHD_set_response_options (struct MHD_Response *response,
|
||||
*/
|
||||
_MHD_EXTERN struct MHD_Response *
|
||||
MHD_create_response_from_callback (uint64_t size,
|
||||
size_t block_size,
|
||||
MHD_ContentReaderCallback crc, void *crc_cls,
|
||||
MHD_ContentReaderFreeCallback crfc);
|
||||
size_t block_size,
|
||||
MHD_ContentReaderCallback crc, void *crc_cls,
|
||||
MHD_ContentReaderFreeCallback crfc);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2953,12 +2992,13 @@ MHD_create_response_from_callback (uint64_t size,
|
||||
* @deprecated use #MHD_create_response_from_buffer instead
|
||||
* @ingroup response
|
||||
*/
|
||||
_MHD_DEPR_FUNC("MHD_create_response_from_data() is deprecated, use MHD_create_response_from_buffer()") \
|
||||
_MHD_EXTERN struct MHD_Response *
|
||||
_MHD_DEPR_FUNC (
|
||||
"MHD_create_response_from_data() is deprecated, use MHD_create_response_from_buffer()") \
|
||||
_MHD_EXTERN struct MHD_Response *
|
||||
MHD_create_response_from_data (size_t size,
|
||||
void *data,
|
||||
int must_free,
|
||||
int must_copy);
|
||||
void *data,
|
||||
int must_free,
|
||||
int must_copy);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3009,8 +3049,8 @@ enum MHD_ResponseMemoryMode
|
||||
*/
|
||||
_MHD_EXTERN struct MHD_Response *
|
||||
MHD_create_response_from_buffer (size_t size,
|
||||
void *buffer,
|
||||
enum MHD_ResponseMemoryMode mode);
|
||||
void *buffer,
|
||||
enum MHD_ResponseMemoryMode mode);
|
||||
|
||||
|
||||
|
||||
@@ -3027,8 +3067,9 @@ MHD_create_response_from_buffer (size_t size,
|
||||
*/
|
||||
_MHD_EXTERN struct MHD_Response *
|
||||
MHD_create_response_from_buffer_with_free_callback (size_t size,
|
||||
void *buffer,
|
||||
MHD_ContentReaderFreeCallback crfc);
|
||||
void *buffer,
|
||||
MHD_ContentReaderFreeCallback
|
||||
crfc);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3044,7 +3085,7 @@ MHD_create_response_from_buffer_with_free_callback (size_t size,
|
||||
*/
|
||||
_MHD_EXTERN struct MHD_Response *
|
||||
MHD_create_response_from_fd (size_t size,
|
||||
int fd);
|
||||
int fd);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3081,18 +3122,20 @@ MHD_create_response_from_fd64 (uint64_t size,
|
||||
* @return NULL on error (i.e. invalid arguments, out of memory)
|
||||
* @ingroup response
|
||||
*/
|
||||
_MHD_DEPR_FUNC("Function MHD_create_response_from_fd_at_offset() is deprecated, use MHD_create_response_from_fd_at_offset64()") \
|
||||
_MHD_EXTERN struct MHD_Response *
|
||||
_MHD_DEPR_FUNC (
|
||||
"Function MHD_create_response_from_fd_at_offset() is deprecated, use MHD_create_response_from_fd_at_offset64()") \
|
||||
_MHD_EXTERN struct MHD_Response *
|
||||
MHD_create_response_from_fd_at_offset (size_t size,
|
||||
int fd,
|
||||
off_t offset);
|
||||
|
||||
#if !defined(_MHD_NO_DEPR_IN_MACRO) || defined(_MHD_NO_DEPR_FUNC)
|
||||
#if ! defined(_MHD_NO_DEPR_IN_MACRO) || defined(_MHD_NO_DEPR_FUNC)
|
||||
/* Substitute MHD_create_response_from_fd_at_offset64() instead of MHD_create_response_from_fd_at_offset()
|
||||
to minimize potential problems with different off_t sizes */
|
||||
#define MHD_create_response_from_fd_at_offset(size,fd,offset) \
|
||||
_MHD_DEPR_IN_MACRO("Usage of MHD_create_response_from_fd_at_offset() is deprecated, use MHD_create_response_from_fd_at_offset64()") \
|
||||
MHD_create_response_from_fd_at_offset64((size),(fd),(offset))
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Usage of MHD_create_response_from_fd_at_offset() is deprecated, use MHD_create_response_from_fd_at_offset64()") \
|
||||
MHD_create_response_from_fd_at_offset64 ((size),(fd),(offset))
|
||||
#endif /* !_MHD_NO_DEPR_IN_MACRO || _MHD_NO_DEPR_FUNC */
|
||||
|
||||
|
||||
@@ -3261,7 +3304,7 @@ typedef void
|
||||
*/
|
||||
_MHD_EXTERN struct MHD_Response *
|
||||
MHD_create_response_for_upgrade (MHD_UpgradeHandler upgrade_handler,
|
||||
void *upgrade_handler_cls);
|
||||
void *upgrade_handler_cls);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3290,7 +3333,7 @@ MHD_destroy_response (struct MHD_Response *response);
|
||||
_MHD_EXTERN int
|
||||
MHD_add_response_header (struct MHD_Response *response,
|
||||
const char *header,
|
||||
const char *content);
|
||||
const char *content);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3305,7 +3348,7 @@ MHD_add_response_header (struct MHD_Response *response,
|
||||
_MHD_EXTERN int
|
||||
MHD_add_response_footer (struct MHD_Response *response,
|
||||
const char *footer,
|
||||
const char *content);
|
||||
const char *content);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3320,7 +3363,7 @@ MHD_add_response_footer (struct MHD_Response *response,
|
||||
_MHD_EXTERN int
|
||||
MHD_del_response_header (struct MHD_Response *response,
|
||||
const char *header,
|
||||
const char *content);
|
||||
const char *content);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3336,7 +3379,7 @@ MHD_del_response_header (struct MHD_Response *response,
|
||||
_MHD_EXTERN int
|
||||
MHD_get_response_headers (struct MHD_Response *response,
|
||||
MHD_KeyValueIterator iterator,
|
||||
void *iterator_cls);
|
||||
void *iterator_cls);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3349,7 +3392,7 @@ MHD_get_response_headers (struct MHD_Response *response,
|
||||
*/
|
||||
_MHD_EXTERN const char *
|
||||
MHD_get_response_header (struct MHD_Response *response,
|
||||
const char *key);
|
||||
const char *key);
|
||||
|
||||
|
||||
/* ********************** PostProcessor functions ********************** */
|
||||
@@ -3381,8 +3424,8 @@ MHD_get_response_header (struct MHD_Response *response,
|
||||
*/
|
||||
_MHD_EXTERN struct MHD_PostProcessor *
|
||||
MHD_create_post_processor (struct MHD_Connection *connection,
|
||||
size_t buffer_size,
|
||||
MHD_PostDataIterator iter, void *iter_cls);
|
||||
size_t buffer_size,
|
||||
MHD_PostDataIterator iter, void *iter_cls);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3433,7 +3476,7 @@ MHD_destroy_post_processor (struct MHD_PostProcessor *pp);
|
||||
*
|
||||
* @param connection The MHD connection structure
|
||||
* @return NULL if no username could be found, a pointer
|
||||
* to the username if found, free using #MHD_free().
|
||||
* to the username if found, free using #MHD_free().
|
||||
* @ingroup authentication
|
||||
*/
|
||||
_MHD_EXTERN char *
|
||||
@@ -3455,7 +3498,8 @@ MHD_free (void *ptr);
|
||||
/**
|
||||
* Which digest algorithm should MHD use for HTTP digest authentication?
|
||||
*/
|
||||
enum MHD_DigestAuthAlgorithm {
|
||||
enum MHD_DigestAuthAlgorithm
|
||||
{
|
||||
|
||||
/**
|
||||
* MHD should pick (currently defaults to SHA-256).
|
||||
@@ -3483,19 +3527,19 @@ enum MHD_DigestAuthAlgorithm {
|
||||
* @param username The username needs to be authenticated
|
||||
* @param password The password used in the authentication
|
||||
* @param nonce_timeout The amount of time for a nonce to be
|
||||
* invalid in seconds
|
||||
* invalid in seconds
|
||||
* @param algo digest algorithms allowed for verification
|
||||
* @return #MHD_YES if authenticated, #MHD_NO if not,
|
||||
* #MHD_INVALID_NONCE if nonce is invalid
|
||||
* #MHD_INVALID_NONCE if nonce is invalid
|
||||
* @ingroup authentication
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_digest_auth_check2 (struct MHD_Connection *connection,
|
||||
const char *realm,
|
||||
const char *username,
|
||||
const char *password,
|
||||
unsigned int nonce_timeout,
|
||||
enum MHD_DigestAuthAlgorithm algo);
|
||||
const char *realm,
|
||||
const char *username,
|
||||
const char *password,
|
||||
unsigned int nonce_timeout,
|
||||
enum MHD_DigestAuthAlgorithm algo);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3510,18 +3554,18 @@ MHD_digest_auth_check2 (struct MHD_Connection *connection,
|
||||
* @param username The username needs to be authenticated
|
||||
* @param password The password used in the authentication
|
||||
* @param nonce_timeout The amount of time for a nonce to be
|
||||
* invalid in seconds
|
||||
* invalid in seconds
|
||||
* @return #MHD_YES if authenticated, #MHD_NO if not,
|
||||
* #MHD_INVALID_NONCE if nonce is invalid
|
||||
* #MHD_INVALID_NONCE if nonce is invalid
|
||||
* @ingroup authentication
|
||||
* @deprecated use MHD_digest_auth_check2()
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_digest_auth_check (struct MHD_Connection *connection,
|
||||
const char *realm,
|
||||
const char *username,
|
||||
const char *password,
|
||||
unsigned int nonce_timeout);
|
||||
const char *realm,
|
||||
const char *username,
|
||||
const char *password,
|
||||
unsigned int nonce_timeout);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3531,24 +3575,24 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
|
||||
* @param realm The realm presented to the client
|
||||
* @param username The username needs to be authenticated
|
||||
* @param digest An `unsigned char *' pointer to the binary MD5 sum
|
||||
* for the precalculated hash value "username:realm:password"
|
||||
* of @a digest_size bytes
|
||||
* for the precalculated hash value "username:realm:password"
|
||||
* of @a digest_size bytes
|
||||
* @param digest_size number of bytes in @a digest (size must match @a algo!)
|
||||
* @param nonce_timeout The amount of time for a nonce to be
|
||||
* invalid in seconds
|
||||
* invalid in seconds
|
||||
* @param algo digest algorithms allowed for verification
|
||||
* @return #MHD_YES if authenticated, #MHD_NO if not,
|
||||
* #MHD_INVALID_NONCE if nonce is invalid
|
||||
* #MHD_INVALID_NONCE if nonce is invalid
|
||||
* @ingroup authentication
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_digest_auth_check_digest2 (struct MHD_Connection *connection,
|
||||
const char *realm,
|
||||
const char *username,
|
||||
const uint8_t *digest,
|
||||
const char *realm,
|
||||
const char *username,
|
||||
const uint8_t *digest,
|
||||
size_t digest_size,
|
||||
unsigned int nonce_timeout,
|
||||
enum MHD_DigestAuthAlgorithm algo);
|
||||
unsigned int nonce_timeout,
|
||||
enum MHD_DigestAuthAlgorithm algo);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3560,21 +3604,21 @@ MHD_digest_auth_check_digest2 (struct MHD_Connection *connection,
|
||||
* @param realm The realm presented to the client
|
||||
* @param username The username needs to be authenticated
|
||||
* @param digest An `unsigned char *' pointer to the binary hash
|
||||
* for the precalculated hash value "username:realm:password";
|
||||
* length must be #MHD_MD5_DIGEST_SIZE bytes
|
||||
* for the precalculated hash value "username:realm:password";
|
||||
* length must be #MHD_MD5_DIGEST_SIZE bytes
|
||||
* @param nonce_timeout The amount of time for a nonce to be
|
||||
* invalid in seconds
|
||||
* invalid in seconds
|
||||
* @return #MHD_YES if authenticated, #MHD_NO if not,
|
||||
* #MHD_INVALID_NONCE if nonce is invalid
|
||||
* #MHD_INVALID_NONCE if nonce is invalid
|
||||
* @ingroup authentication
|
||||
* @deprecated use #MHD_digest_auth_check_digest2()
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_digest_auth_check_digest (struct MHD_Connection *connection,
|
||||
const char *realm,
|
||||
const char *username,
|
||||
const uint8_t digest[MHD_MD5_DIGEST_SIZE],
|
||||
unsigned int nonce_timeout);
|
||||
const char *realm,
|
||||
const char *username,
|
||||
const uint8_t digest[MHD_MD5_DIGEST_SIZE],
|
||||
unsigned int nonce_timeout);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3587,18 +3631,18 @@ MHD_digest_auth_check_digest (struct MHD_Connection *connection,
|
||||
* body; note that this function will set the "WWW Authenticate"
|
||||
* header and that the caller should not do this
|
||||
* @param signal_stale #MHD_YES if the nonce is invalid to add
|
||||
* 'stale=true' to the authentication header
|
||||
* 'stale=true' to the authentication header
|
||||
* @param algo digest algorithm to use
|
||||
* @return #MHD_YES on success, #MHD_NO otherwise
|
||||
* @ingroup authentication
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
|
||||
const char *realm,
|
||||
const char *opaque,
|
||||
struct MHD_Response *response,
|
||||
int signal_stale,
|
||||
enum MHD_DigestAuthAlgorithm algo);
|
||||
const char *realm,
|
||||
const char *opaque,
|
||||
struct MHD_Response *response,
|
||||
int signal_stale,
|
||||
enum MHD_DigestAuthAlgorithm algo);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3613,17 +3657,17 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
|
||||
* body; note that this function will set the "WWW Authenticate"
|
||||
* header and that the caller should not do this
|
||||
* @param signal_stale #MHD_YES if the nonce is invalid to add
|
||||
* 'stale=true' to the authentication header
|
||||
* 'stale=true' to the authentication header
|
||||
* @return #MHD_YES on success, #MHD_NO otherwise
|
||||
* @ingroup authentication
|
||||
* @deprecated use MHD_queue_auth_fail_response2()
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_queue_auth_fail_response (struct MHD_Connection *connection,
|
||||
const char *realm,
|
||||
const char *opaque,
|
||||
struct MHD_Response *response,
|
||||
int signal_stale);
|
||||
const char *realm,
|
||||
const char *opaque,
|
||||
struct MHD_Response *response,
|
||||
int signal_stale);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3632,12 +3676,12 @@ MHD_queue_auth_fail_response (struct MHD_Connection *connection,
|
||||
* @param connection The MHD connection structure
|
||||
* @param[out] password a pointer for the password, free using #MHD_free().
|
||||
* @return NULL if no username could be found, a pointer
|
||||
* to the username if found, free using #MHD_free().
|
||||
* to the username if found, free using #MHD_free().
|
||||
* @ingroup authentication
|
||||
*/
|
||||
_MHD_EXTERN char *
|
||||
MHD_basic_auth_get_username_password (struct MHD_Connection *connection,
|
||||
char** password);
|
||||
char**password);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3654,8 +3698,8 @@ MHD_basic_auth_get_username_password (struct MHD_Connection *connection,
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_queue_basic_auth_fail_response (struct MHD_Connection *connection,
|
||||
const char *realm,
|
||||
struct MHD_Response *response);
|
||||
const char *realm,
|
||||
struct MHD_Response *response);
|
||||
|
||||
/* ********************** generic query functions ********************** */
|
||||
|
||||
@@ -3672,8 +3716,8 @@ MHD_queue_basic_auth_fail_response (struct MHD_Connection *connection,
|
||||
*/
|
||||
_MHD_EXTERN const union MHD_ConnectionInfo *
|
||||
MHD_get_connection_info (struct MHD_Connection *connection,
|
||||
enum MHD_ConnectionInfoType info_type,
|
||||
...);
|
||||
enum MHD_ConnectionInfoType info_type,
|
||||
...);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3706,8 +3750,8 @@ enum MHD_CONNECTION_OPTION
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_set_connection_option (struct MHD_Connection *connection,
|
||||
enum MHD_CONNECTION_OPTION option,
|
||||
...);
|
||||
enum MHD_CONNECTION_OPTION option,
|
||||
...);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3770,8 +3814,8 @@ union MHD_DaemonInfo
|
||||
*/
|
||||
_MHD_EXTERN const union MHD_DaemonInfo *
|
||||
MHD_get_daemon_info (struct MHD_Daemon *daemon,
|
||||
enum MHD_DaemonInfoType info_type,
|
||||
...);
|
||||
enum MHD_DaemonInfoType info_type,
|
||||
...);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
+257
-231
@@ -99,9 +99,9 @@ extern "C"
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#if defined(_WIN32) && ! defined(__CYGWIN__)
|
||||
#include <ws2tcpip.h>
|
||||
#if defined(_MSC_FULL_VER) && !defined (_SSIZE_T_DEFINED)
|
||||
#if defined(_MSC_FULL_VER) && ! defined (_SSIZE_T_DEFINED)
|
||||
#define _SSIZE_T_DEFINED
|
||||
typedef intptr_t ssize_t;
|
||||
#endif /* !_SSIZE_T_DEFINED */
|
||||
@@ -112,7 +112,7 @@ typedef intptr_t ssize_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__) && !defined(_SYS_TYPES_FD_SET)
|
||||
#if defined(__CYGWIN__) && ! defined(_SYS_TYPES_FD_SET)
|
||||
/* Do not define __USE_W32_SOCKETS under Cygwin! */
|
||||
#error Cygwin with winsock fd_set is not supported
|
||||
#endif
|
||||
@@ -179,7 +179,7 @@ enum MHD_Bool
|
||||
/**
|
||||
* MHD_socket is type for socket FDs
|
||||
*/
|
||||
#if !defined(_WIN32) || defined(_SYS_TYPES_FD_SET)
|
||||
#if ! defined(_WIN32) || defined(_SYS_TYPES_FD_SET)
|
||||
#define MHD_POSIX_SOCKETS 1
|
||||
typedef int MHD_socket;
|
||||
#define MHD_INVALID_SOCKET (-1)
|
||||
@@ -204,30 +204,35 @@ typedef SOCKET MHD_socket;
|
||||
#endif /* MHD_NO_DEPRECATION */
|
||||
|
||||
#ifndef _MHD_DEPR_MACRO
|
||||
#if defined(_MSC_FULL_VER) && _MSC_VER+0 >= 1500
|
||||
#if defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1500
|
||||
/* VS 2008 or later */
|
||||
/* Stringify macros */
|
||||
#define _MHD_INSTRMACRO(a) #a
|
||||
#define _MHD_STRMACRO(a) _MHD_INSTRMACRO(a)
|
||||
#define _MHD_STRMACRO(a) _MHD_INSTRMACRO (a)
|
||||
/* deprecation message */
|
||||
#define _MHD_DEPR_MACRO(msg) __pragma(message(__FILE__ "(" _MHD_STRMACRO(__LINE__)"): warning: " msg))
|
||||
#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO(msg)
|
||||
#define _MHD_DEPR_MACRO(msg) __pragma (message (__FILE__ "(" _MHD_STRMACRO ( \
|
||||
__LINE__) "): warning: " msg))
|
||||
#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO (msg)
|
||||
#elif defined(__clang__) || defined (__GNUC_PATCHLEVEL__)
|
||||
/* clang or GCC since 3.0 */
|
||||
#define _MHD_GCC_PRAG(x) _Pragma (#x)
|
||||
#if (defined(__clang__) && (__clang_major__+0 >= 5 || \
|
||||
(!defined(__apple_build_version__) && (__clang_major__+0 > 3 || (__clang_major__+0 == 3 && __clang_minor__ >= 3))))) || \
|
||||
__GNUC__+0 > 4 || (__GNUC__+0 == 4 && __GNUC_MINOR__+0 >= 8)
|
||||
#if (defined(__clang__) && (__clang_major__ + 0 >= 5 || \
|
||||
(! defined(__apple_build_version__) && \
|
||||
(__clang_major__ + 0 > 3 || (__clang_major__ + 0 == 3 && __clang_minor__ >= \
|
||||
3))))) || \
|
||||
__GNUC__ + 0 > 4 || (__GNUC__ + 0 == 4 && __GNUC_MINOR__ + 0 >= 8)
|
||||
/* clang >= 3.3 (or XCode's clang >= 5.0) or
|
||||
GCC >= 4.8 */
|
||||
#define _MHD_DEPR_MACRO(msg) _MHD_GCC_PRAG(GCC warning msg)
|
||||
#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO(msg)
|
||||
#define _MHD_DEPR_MACRO(msg) _MHD_GCC_PRAG (GCC warning msg)
|
||||
#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO (msg)
|
||||
#else /* older clang or GCC */
|
||||
/* clang < 3.3, XCode's clang < 5.0, 3.0 <= GCC < 4.8 */
|
||||
#define _MHD_DEPR_MACRO(msg) _MHD_GCC_PRAG(message msg)
|
||||
#if (defined(__clang__) && (__clang_major__+0 > 2 || (__clang_major__+0 == 2 && __clang_minor__ >= 9))) /* FIXME: clang >= 2.9, earlier versions not tested */
|
||||
#define _MHD_DEPR_MACRO(msg) _MHD_GCC_PRAG (message msg)
|
||||
#if (defined(__clang__) && (__clang_major__ + 0 > 2 || (__clang_major__ + 0 == \
|
||||
2 && __clang_minor__ >= \
|
||||
9))) /* FIXME: clang >= 2.9, earlier versions not tested */
|
||||
/* clang handles inline pragmas better than GCC */
|
||||
#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO(msg)
|
||||
#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO (msg)
|
||||
#endif /* clang >= 2.9 */
|
||||
#endif /* older clang or GCC */
|
||||
/* #elif defined(SOMEMACRO) */ /* add compiler-specific macros here if required */
|
||||
@@ -244,17 +249,19 @@ typedef SOCKET MHD_socket;
|
||||
#endif /* !_MHD_DEPR_IN_MACRO */
|
||||
|
||||
#ifndef _MHD_DEPR_FUNC
|
||||
#if defined(_MSC_FULL_VER) && _MSC_VER+0 >= 1400
|
||||
#if defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1400
|
||||
/* VS 2005 or later */
|
||||
#define _MHD_DEPR_FUNC(msg) __declspec(deprecated(msg))
|
||||
#elif defined(_MSC_FULL_VER) && _MSC_VER+0 >= 1310
|
||||
#define _MHD_DEPR_FUNC(msg) __declspec(deprecated (msg))
|
||||
#elif defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1310
|
||||
/* VS .NET 2003 deprecation do not support custom messages */
|
||||
#define _MHD_DEPR_FUNC(msg) __declspec(deprecated)
|
||||
#elif (__GNUC__+0 >= 5) || (defined (__clang__) && \
|
||||
(__clang_major__+0 > 2 || (__clang_major__+0 == 2 && __clang_minor__ >= 9))) /* FIXME: earlier versions not tested */
|
||||
#elif (__GNUC__ + 0 >= 5) || (defined (__clang__) && \
|
||||
(__clang_major__ + 0 > 2 || (__clang_major__ + 0 == 2 && __clang_minor__ >= \
|
||||
9))) /* FIXME: earlier versions not tested */
|
||||
/* GCC >= 5.0 or clang >= 2.9 */
|
||||
#define _MHD_DEPR_FUNC(msg) __attribute__((deprecated(msg)))
|
||||
#elif defined (__clang__) || __GNUC__+0 > 3 || (__GNUC__+0 == 3 && __GNUC_MINOR__+0 >= 1)
|
||||
#define _MHD_DEPR_FUNC(msg) __attribute__((deprecated (msg)))
|
||||
#elif defined (__clang__) || __GNUC__ + 0 > 3 || (__GNUC__ + 0 == 3 && \
|
||||
__GNUC_MINOR__ + 0 >= 1)
|
||||
/* 3.1 <= GCC < 5.0 or clang < 2.9 */
|
||||
/* old GCC-style deprecation do not support custom messages */
|
||||
#define _MHD_DEPR_FUNC(msg) __attribute__((__deprecated__))
|
||||
@@ -277,7 +284,7 @@ typedef SOCKET MHD_socket;
|
||||
#if defined(__CYGWIN__) || defined(_WIN32) || defined(MHD_W32LIB)
|
||||
#define MHD_NONNULL(...) /* empty */
|
||||
#else
|
||||
#define MHD_NONNULL(...) __THROW __nonnull((__VA_ARGS__))
|
||||
#define MHD_NONNULL(...) __THROW __nonnull ((__VA_ARGS__))
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -1110,8 +1117,8 @@ enum MHD_Method
|
||||
*/
|
||||
MHD_METHOD_VERSION_CONTROL = 38
|
||||
|
||||
/* For more, check:
|
||||
https://www.iana.org/assignments/http-methods/http-methods.xhtml */
|
||||
/* For more, check:
|
||||
https://www.iana.org/assignments/http-methods/http-methods.xhtml */
|
||||
|
||||
};
|
||||
|
||||
@@ -1123,7 +1130,8 @@ enum MHD_Method
|
||||
* See also: http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4
|
||||
* @{
|
||||
*/
|
||||
#define MHD_HTTP_POST_ENCODING_FORM_URLENCODED "application/x-www-form-urlencoded"
|
||||
#define MHD_HTTP_POST_ENCODING_FORM_URLENCODED \
|
||||
"application/x-www-form-urlencoded"
|
||||
#define MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA "multipart/form-data"
|
||||
|
||||
/** @} */ /* end of group postenc */
|
||||
@@ -1386,7 +1394,8 @@ enum MHD_Method
|
||||
/* Standard. RFC7469 */
|
||||
#define MHD_HTTP_HEADER_PUBLIC_KEY_PINS "Public-Key-Pins"
|
||||
/* Standard. RFC7469 */
|
||||
#define MHD_HTTP_HEADER_PUBLIC_KEY_PINS_REPORT_ONLY "Public-Key-Pins-Report-Only"
|
||||
#define MHD_HTTP_HEADER_PUBLIC_KEY_PINS_REPORT_ONLY \
|
||||
"Public-Key-Pins-Report-Only"
|
||||
/* No category. RFC4437 */
|
||||
#define MHD_HTTP_HEADER_REDIRECT_REF "Redirect-Ref"
|
||||
/* No category. RFC4229 */
|
||||
@@ -1445,7 +1454,8 @@ enum MHD_Method
|
||||
#define MHD_HTTP_HEADER_X_FRAME_OPTIONS "X-Frame-Options"
|
||||
|
||||
/* Some provisional headers. */
|
||||
#define MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN "Access-Control-Allow-Origin"
|
||||
#define MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN \
|
||||
"Access-Control-Allow-Origin"
|
||||
/** @} */ /* end of group headers */
|
||||
|
||||
|
||||
@@ -1468,9 +1478,9 @@ enum MHD_Method
|
||||
*/
|
||||
typedef const struct MHD_Action *
|
||||
(*MHD_RequestCallback) (void *cls,
|
||||
struct MHD_Request *request,
|
||||
const char *url,
|
||||
enum MHD_Method method);
|
||||
struct MHD_Request *request,
|
||||
const char *url,
|
||||
enum MHD_Method method);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1484,8 +1494,8 @@ typedef const struct MHD_Action *
|
||||
*/
|
||||
_MHD_EXTERN struct MHD_Daemon *
|
||||
MHD_daemon_create (MHD_RequestCallback cb,
|
||||
void *cb_cls)
|
||||
MHD_NONNULL(1);
|
||||
void *cb_cls)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1498,7 +1508,7 @@ MHD_daemon_create (MHD_RequestCallback cb,
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_start (struct MHD_Daemon *daemon)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1523,7 +1533,7 @@ MHD_daemon_start (struct MHD_Daemon *daemon)
|
||||
*/
|
||||
_MHD_EXTERN MHD_socket
|
||||
MHD_daemon_quiesce (struct MHD_Daemon *daemon)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1534,7 +1544,7 @@ MHD_daemon_quiesce (struct MHD_Daemon *daemon)
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_destroy (struct MHD_Daemon *daemon)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1564,10 +1574,10 @@ MHD_daemon_destroy (struct MHD_Daemon *daemon)
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_add_connection (struct MHD_Daemon *daemon,
|
||||
MHD_socket client_socket,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
MHD_NONNULL(1);
|
||||
MHD_socket client_socket,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1596,11 +1606,11 @@ MHD_daemon_add_connection (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_get_fdset (struct MHD_Daemon *daemon,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *except_fd_set,
|
||||
MHD_socket *max_fd)
|
||||
MHD_NONNULL(1,2,3,4);
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *except_fd_set,
|
||||
MHD_socket *max_fd)
|
||||
MHD_NONNULL (1,2,3,4);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1632,12 +1642,12 @@ MHD_daemon_get_fdset (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_get_fdset2 (struct MHD_Daemon *daemon,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *except_fd_set,
|
||||
MHD_socket *max_fd,
|
||||
unsigned int fd_setsize)
|
||||
MHD_NONNULL(1,2,3,4);
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *except_fd_set,
|
||||
MHD_socket *max_fd,
|
||||
unsigned int fd_setsize)
|
||||
MHD_NONNULL (1,2,3,4);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1662,8 +1672,10 @@ MHD_daemon_get_fdset2 (struct MHD_Daemon *daemon,
|
||||
* fit fd_set.
|
||||
* @ingroup event
|
||||
*/
|
||||
#define MHD_daemon_get_fdset(daemon,read_fd_set,write_fd_set,except_fd_set,max_fd) \
|
||||
MHD_get_fdset2((daemon),(read_fd_set),(write_fd_set),(except_fd_set),(max_fd),FD_SETSIZE)
|
||||
#define MHD_daemon_get_fdset(daemon,read_fd_set,write_fd_set,except_fd_set, \
|
||||
max_fd) \
|
||||
MHD_get_fdset2 ((daemon),(read_fd_set),(write_fd_set),(except_fd_set), \
|
||||
(max_fd),FD_SETSIZE)
|
||||
|
||||
|
||||
/**
|
||||
@@ -1687,8 +1699,8 @@ MHD_daemon_get_fdset2 (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_get_timeout (struct MHD_Daemon *daemon,
|
||||
MHD_UNSIGNED_LONG_LONG *timeout)
|
||||
MHD_NONNULL(1,2);
|
||||
MHD_UNSIGNED_LONG_LONG *timeout)
|
||||
MHD_NONNULL (1,2);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1711,7 +1723,7 @@ MHD_daemon_get_timeout (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_run (struct MHD_Daemon *daemon)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1738,10 +1750,10 @@ MHD_daemon_run (struct MHD_Daemon *daemon)
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_run_from_select (struct MHD_Daemon *daemon,
|
||||
const fd_set *read_fd_set,
|
||||
const fd_set *write_fd_set,
|
||||
const fd_set *except_fd_set)
|
||||
MHD_NONNULL(1,2,3,4);
|
||||
const fd_set *read_fd_set,
|
||||
const fd_set *write_fd_set,
|
||||
const fd_set *except_fd_set)
|
||||
MHD_NONNULL (1,2,3,4);
|
||||
|
||||
|
||||
/* ********************* daemon options ************** */
|
||||
@@ -1758,9 +1770,9 @@ MHD_daemon_run_from_select (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
typedef void
|
||||
(*MHD_LoggingCallback)(void *cls,
|
||||
enum MHD_StatusCode sc,
|
||||
const char *fm,
|
||||
va_list ap);
|
||||
enum MHD_StatusCode sc,
|
||||
const char *fm,
|
||||
va_list ap);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1774,9 +1786,9 @@ typedef void
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_set_logger (struct MHD_Daemon *daemon,
|
||||
MHD_LoggingCallback logger,
|
||||
void *logger_cls)
|
||||
MHD_NONNULL(1);
|
||||
MHD_LoggingCallback logger,
|
||||
void *logger_cls)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1784,7 +1796,8 @@ MHD_daemon_set_logger (struct MHD_Daemon *daemon,
|
||||
*
|
||||
* @param daemon which instance to disable logging for
|
||||
*/
|
||||
#define MHD_daemon_disable_logging(daemon) MHD_daemon_set_logger (daemon, NULL, NULL)
|
||||
#define MHD_daemon_disable_logging(daemon) MHD_daemon_set_logger (daemon, NULL, \
|
||||
NULL)
|
||||
|
||||
|
||||
/**
|
||||
@@ -1794,7 +1807,7 @@ MHD_daemon_set_logger (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_suppress_date_no_clock (struct MHD_Daemon *daemon)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1816,7 +1829,7 @@ MHD_daemon_suppress_date_no_clock (struct MHD_Daemon *daemon)
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_disable_itc (struct MHD_Daemon *daemon)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1829,7 +1842,7 @@ MHD_daemon_disable_itc (struct MHD_Daemon *daemon)
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_enable_turbo (struct MHD_Daemon *daemon)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1843,7 +1856,7 @@ MHD_daemon_enable_turbo (struct MHD_Daemon *daemon)
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_disallow_suspend_resume (struct MHD_Daemon *daemon)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1859,7 +1872,7 @@ MHD_daemon_disallow_suspend_resume (struct MHD_Daemon *daemon)
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_disallow_upgrade (struct MHD_Daemon *daemon)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1904,9 +1917,9 @@ enum MHD_FastOpenMethod
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_Bool
|
||||
MHD_daemon_tcp_fastopen (struct MHD_Daemon *daemon,
|
||||
enum MHD_FastOpenMethod fom,
|
||||
unsigned int queue_length)
|
||||
MHD_NONNULL(1);
|
||||
enum MHD_FastOpenMethod fom,
|
||||
unsigned int queue_length)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1958,9 +1971,9 @@ enum MHD_AddressFamily
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_bind_port (struct MHD_Daemon *daemon,
|
||||
enum MHD_AddressFamily af,
|
||||
uint16_t port)
|
||||
MHD_NONNULL(1);
|
||||
enum MHD_AddressFamily af,
|
||||
uint16_t port)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1974,9 +1987,9 @@ MHD_daemon_bind_port (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_bind_socket_address (struct MHD_Daemon *daemon,
|
||||
const struct sockaddr *sa,
|
||||
size_t sa_len)
|
||||
MHD_NONNULL(1);
|
||||
const struct sockaddr *sa,
|
||||
size_t sa_len)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1988,8 +2001,8 @@ MHD_daemon_bind_socket_address (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_listen_backlog (struct MHD_Daemon *daemon,
|
||||
int listen_backlog)
|
||||
MHD_NONNULL(1);
|
||||
int listen_backlog)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2004,7 +2017,7 @@ MHD_daemon_listen_backlog (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_listen_allow_address_reuse (struct MHD_Daemon *daemon)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2023,8 +2036,8 @@ MHD_daemon_listen_allow_address_reuse (struct MHD_Daemon *daemon)
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_listen_socket (struct MHD_Daemon *daemon,
|
||||
MHD_socket listen_socket)
|
||||
MHD_NONNULL(1);
|
||||
MHD_socket listen_socket)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2064,8 +2077,8 @@ enum MHD_EventLoopSyscall
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_Bool
|
||||
MHD_daemon_event_loop (struct MHD_Daemon *daemon,
|
||||
enum MHD_EventLoopSyscall els)
|
||||
MHD_NONNULL(1);
|
||||
enum MHD_EventLoopSyscall els)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2109,8 +2122,8 @@ enum MHD_ProtocolStrictLevel
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_protocol_strict_level (struct MHD_Daemon *daemon,
|
||||
enum MHD_ProtocolStrictLevel sl)
|
||||
MHD_NONNULL(1);
|
||||
enum MHD_ProtocolStrictLevel sl)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2121,7 +2134,7 @@ MHD_daemon_protocol_strict_level (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_enable_shoutcast (struct MHD_Daemon *daemon)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2141,9 +2154,9 @@ MHD_daemon_enable_shoutcast (struct MHD_Daemon *daemon)
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_set_tls_backend (struct MHD_Daemon *daemon,
|
||||
const char *tls_backend,
|
||||
const char *ciphers)
|
||||
MHD_NONNULL(1);
|
||||
const char *tls_backend,
|
||||
const char *ciphers)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2160,10 +2173,10 @@ MHD_daemon_set_tls_backend (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_tls_key_and_cert_from_memory (struct MHD_Daemon *daemon,
|
||||
const char *mem_key,
|
||||
const char *mem_cert,
|
||||
const char *pass)
|
||||
MHD_NONNULL(1,2,3);
|
||||
const char *mem_key,
|
||||
const char *mem_cert,
|
||||
const char *pass)
|
||||
MHD_NONNULL (1,2,3);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2176,8 +2189,8 @@ MHD_daemon_tls_key_and_cert_from_memory (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_tls_mem_dhparams (struct MHD_Daemon *daemon,
|
||||
const char *dh)
|
||||
MHD_NONNULL(1);
|
||||
const char *dh)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2190,14 +2203,14 @@ MHD_daemon_tls_mem_dhparams (struct MHD_Daemon *daemon,
|
||||
* @param[out] psk to be set to the pre-shared-key; should be allocated with malloc(),
|
||||
* will be freed by MHD
|
||||
* @param[out] psk_size to be set to the number of bytes in @a psk
|
||||
* @return 0 on success, -1 on errors
|
||||
* @return 0 on success, -1 on errors
|
||||
*/
|
||||
typedef int
|
||||
(*MHD_PskServerCredentialsCallback)(void *cls,
|
||||
const struct MHD_Connection *connection,
|
||||
const char *username,
|
||||
void **psk,
|
||||
size_t *psk_size);
|
||||
const struct MHD_Connection *connection,
|
||||
const char *username,
|
||||
void **psk,
|
||||
size_t *psk_size);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2210,9 +2223,9 @@ typedef int
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_set_tls_psk_callback (struct MHD_Daemon *daemon,
|
||||
MHD_PskServerCredentialsCallback psk_cb,
|
||||
void *psk_cb_cls)
|
||||
MHD_NONNULL(1);
|
||||
MHD_PskServerCredentialsCallback psk_cb,
|
||||
void *psk_cb_cls)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2225,8 +2238,8 @@ MHD_daemon_set_tls_psk_callback (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_tls_mem_trust (struct MHD_Daemon *daemon,
|
||||
const char *mem_trust)
|
||||
MHD_NONNULL(1);
|
||||
const char *mem_trust)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2238,8 +2251,8 @@ MHD_daemon_tls_mem_trust (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_gnutls_credentials (struct MHD_Daemon *daemon,
|
||||
int gnutls_credentials)
|
||||
MHD_NONNULL(1);
|
||||
int gnutls_credentials)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2261,8 +2274,8 @@ MHD_daemon_gnutls_credentials (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_gnutls_key_and_cert_from_callback (struct MHD_Daemon *daemon,
|
||||
void *cb)
|
||||
MHD_NONNULL(1);
|
||||
void *cb)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2308,7 +2321,7 @@ enum MHD_ThreadingMode
|
||||
*
|
||||
* @return an `enum MHD_ThreadingMode` for a thread pool of size @a n
|
||||
*/
|
||||
#define MHD_TM_THREAD_POOL(n) ((enum MHD_ThreadingMode)(n))
|
||||
#define MHD_TM_THREAD_POOL(n) ((enum MHD_ThreadingMode) (n))
|
||||
|
||||
|
||||
/**
|
||||
@@ -2320,8 +2333,8 @@ enum MHD_ThreadingMode
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_threading_mode (struct MHD_Daemon *daemon,
|
||||
enum MHD_ThreadingMode tm)
|
||||
MHD_NONNULL(1);
|
||||
enum MHD_ThreadingMode tm)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2334,9 +2347,9 @@ MHD_daemon_threading_mode (struct MHD_Daemon *daemon,
|
||||
* @return #MHD_YES if connection is allowed, #MHD_NO if not
|
||||
*/
|
||||
typedef enum MHD_Bool
|
||||
(*MHD_AcceptPolicyCallback) (void *cls,
|
||||
const struct sockaddr *addr,
|
||||
size_t addrlen);
|
||||
(*MHD_AcceptPolicyCallback)(void *cls,
|
||||
const struct sockaddr *addr,
|
||||
size_t addrlen);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2350,9 +2363,9 @@ typedef enum MHD_Bool
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_accept_policy (struct MHD_Daemon *daemon,
|
||||
MHD_AcceptPolicyCallback apc,
|
||||
void *apc_cls)
|
||||
MHD_NONNULL(1);
|
||||
MHD_AcceptPolicyCallback apc,
|
||||
void *apc_cls)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2367,8 +2380,8 @@ MHD_daemon_accept_policy (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
typedef void *
|
||||
(*MHD_EarlyUriLogCallback)(void *cls,
|
||||
const char *uri,
|
||||
struct MHD_Request *request);
|
||||
const char *uri,
|
||||
struct MHD_Request *request);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2382,9 +2395,9 @@ typedef void *
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_set_early_uri_logger (struct MHD_Daemon *daemon,
|
||||
MHD_EarlyUriLogCallback cb,
|
||||
void *cb_cls)
|
||||
MHD_NONNULL(1);
|
||||
MHD_EarlyUriLogCallback cb,
|
||||
void *cb_cls)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2431,8 +2444,8 @@ enum MHD_ConnectionNotificationCode
|
||||
*/
|
||||
typedef void
|
||||
(*MHD_NotifyConnectionCallback) (void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
enum MHD_ConnectionNotificationCode toe);
|
||||
struct MHD_Connection *connection,
|
||||
enum MHD_ConnectionNotificationCode toe);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2445,9 +2458,9 @@ typedef void
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_set_notify_connection (struct MHD_Daemon *daemon,
|
||||
MHD_NotifyConnectionCallback ncc,
|
||||
void *ncc_cls)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NotifyConnectionCallback ncc,
|
||||
void *ncc_cls)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2463,9 +2476,9 @@ MHD_daemon_set_notify_connection (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_connection_memory_limit (struct MHD_Daemon *daemon,
|
||||
size_t memory_limit_b,
|
||||
size_t memory_increment_b)
|
||||
MHD_NONNULL(1);
|
||||
size_t memory_limit_b,
|
||||
size_t memory_increment_b)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2478,8 +2491,8 @@ MHD_daemon_connection_memory_limit (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_thread_stack_size (struct MHD_Daemon *daemon,
|
||||
size_t stack_limit_b)
|
||||
MHD_NONNULL(1);
|
||||
size_t stack_limit_b)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2499,9 +2512,9 @@ MHD_daemon_thread_stack_size (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_connection_limits (struct MHD_Daemon *daemon,
|
||||
unsigned int global_connection_limit,
|
||||
unsigned int ip_connection_limit)
|
||||
MHD_NONNULL(1);
|
||||
unsigned int global_connection_limit,
|
||||
unsigned int ip_connection_limit)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2514,8 +2527,8 @@ MHD_daemon_connection_limits (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_connection_default_timeout (struct MHD_Daemon *daemon,
|
||||
unsigned int timeout_s)
|
||||
MHD_NONNULL(1);
|
||||
unsigned int timeout_s)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2532,8 +2545,8 @@ MHD_daemon_connection_default_timeout (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
typedef size_t
|
||||
(*MHD_UnescapeCallback) (void *cls,
|
||||
struct MHD_Request *req,
|
||||
char *s);
|
||||
struct MHD_Request *req,
|
||||
char *s);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2549,9 +2562,9 @@ typedef size_t
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_unescape_cb (struct MHD_Daemon *daemon,
|
||||
MHD_UnescapeCallback unescape_cb,
|
||||
void *unescape_cb_cls)
|
||||
MHD_NONNULL(1);
|
||||
MHD_UnescapeCallback unescape_cb,
|
||||
void *unescape_cb_cls)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2565,9 +2578,9 @@ MHD_daemon_unescape_cb (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_daemon_digest_auth_random (struct MHD_Daemon *daemon,
|
||||
size_t buf_size,
|
||||
const void *buf)
|
||||
MHD_NONNULL(1,3);
|
||||
size_t buf_size,
|
||||
const void *buf)
|
||||
MHD_NONNULL (1,3);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2579,8 +2592,8 @@ MHD_daemon_digest_auth_random (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_StatusCode
|
||||
MHD_daemon_digest_auth_nc_length (struct MHD_Daemon *daemon,
|
||||
size_t nc_length)
|
||||
MHD_NONNULL(1);
|
||||
size_t nc_length)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/* ********************* connection options ************** */
|
||||
@@ -2596,8 +2609,8 @@ MHD_daemon_digest_auth_nc_length (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_connection_set_timeout (struct MHD_Connection *connection,
|
||||
unsigned int timeout_s)
|
||||
MHD_NONNULL(1);
|
||||
unsigned int timeout_s)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/* **************** Request handling functions ***************** */
|
||||
@@ -2678,10 +2691,10 @@ typedef int
|
||||
*/
|
||||
_MHD_EXTERN unsigned int
|
||||
MHD_request_get_values (struct MHD_Request *request,
|
||||
enum MHD_ValueKind kind,
|
||||
MHD_KeyValueIterator iterator,
|
||||
void *iterator_cls)
|
||||
MHD_NONNULL(1);
|
||||
enum MHD_ValueKind kind,
|
||||
MHD_KeyValueIterator iterator,
|
||||
void *iterator_cls)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2711,10 +2724,10 @@ MHD_request_get_values (struct MHD_Request *request,
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_Bool
|
||||
MHD_request_set_value (struct MHD_Request *request,
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
const char *value)
|
||||
MHD_NONNULL(1,3,4);
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
const char *value)
|
||||
MHD_NONNULL (1,3,4);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2729,9 +2742,9 @@ MHD_request_set_value (struct MHD_Request *request,
|
||||
*/
|
||||
_MHD_EXTERN const char *
|
||||
MHD_request_lookup_value (struct MHD_Request *request,
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key)
|
||||
MHD_NONNULL(1);
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
|
||||
@@ -2741,7 +2754,8 @@ MHD_request_lookup_value (struct MHD_Request *request,
|
||||
* @{
|
||||
*/
|
||||
/* See http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml */
|
||||
enum MHD_HTTP_StatusCode {
|
||||
enum MHD_HTTP_StatusCode
|
||||
{
|
||||
MHD_HTTP_CONTINUE = 100,
|
||||
MHD_HTTP_SWITCHING_PROTOCOLS = 101,
|
||||
MHD_HTTP_PROCESSING = 102,
|
||||
@@ -2777,7 +2791,9 @@ enum MHD_HTTP_StatusCode {
|
||||
MHD_HTTP_NOT_ACCEPTABLE = 406,
|
||||
/** @deprecated */
|
||||
#define MHD_HTTP_METHOD_NOT_ACCEPTABLE \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_HTTP_METHOD_NOT_ACCEPTABLE is deprecated, use MHD_HTTP_NOT_ACCEPTABLE") MHD_HTTP_NOT_ACCEPTABLE
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_HTTP_METHOD_NOT_ACCEPTABLE is deprecated, use MHD_HTTP_NOT_ACCEPTABLE") \
|
||||
MHD_HTTP_NOT_ACCEPTABLE
|
||||
MHD_HTTP_PROXY_AUTHENTICATION_REQUIRED = 407,
|
||||
MHD_HTTP_REQUEST_TIMEOUT = 408,
|
||||
MHD_HTTP_CONFLICT = 409,
|
||||
@@ -2787,16 +2803,22 @@ enum MHD_HTTP_StatusCode {
|
||||
MHD_HTTP_PAYLOAD_TOO_LARGE = 413,
|
||||
/** @deprecated */
|
||||
#define MHD_HTTP_REQUEST_ENTITY_TOO_LARGE \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_HTTP_REQUEST_ENTITY_TOO_LARGE is deprecated, use MHD_HTTP_PAYLOAD_TOO_LARGE") MHD_HTTP_PAYLOAD_TOO_LARGE
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_HTTP_REQUEST_ENTITY_TOO_LARGE is deprecated, use MHD_HTTP_PAYLOAD_TOO_LARGE") \
|
||||
MHD_HTTP_PAYLOAD_TOO_LARGE
|
||||
MHD_HTTP_URI_TOO_LONG = 414,
|
||||
/** @deprecated */
|
||||
#define MHD_HTTP_REQUEST_URI_TOO_LONG \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_HTTP_REQUEST_URI_TOO_LONG is deprecated, use MHD_HTTP_URI_TOO_LONG") MHD_HTTP_URI_TOO_LONG
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_HTTP_REQUEST_URI_TOO_LONG is deprecated, use MHD_HTTP_URI_TOO_LONG") \
|
||||
MHD_HTTP_URI_TOO_LONG
|
||||
MHD_HTTP_UNSUPPORTED_MEDIA_TYPE = 415,
|
||||
MHD_HTTP_RANGE_NOT_SATISFIABLE = 416,
|
||||
/** @deprecated */
|
||||
#define MHD_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE \
|
||||
_MHD_DEPR_IN_MACRO("Value MHD_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE is deprecated, use MHD_HTTP_RANGE_NOT_SATISFIABLE") MHD_HTTP_RANGE_NOT_SATISFIABLE
|
||||
_MHD_DEPR_IN_MACRO ( \
|
||||
"Value MHD_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE is deprecated, use MHD_HTTP_RANGE_NOT_SATISFIABLE") \
|
||||
MHD_HTTP_RANGE_NOT_SATISFIABLE
|
||||
MHD_HTTP_EXPECTATION_FAILED = 417,
|
||||
|
||||
MHD_HTTP_MISDIRECTED_REQUEST = 421,
|
||||
@@ -2903,7 +2925,7 @@ MHD_action_suspend (void);
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_request_resume (struct MHD_Request *request)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/* **************** Response manipulation functions ***************** */
|
||||
@@ -2936,8 +2958,8 @@ struct MHD_Response;
|
||||
*/
|
||||
_MHD_EXTERN const struct MHD_Action *
|
||||
MHD_action_from_response (struct MHD_Response *response,
|
||||
enum MHD_Bool destroy_after_use)
|
||||
MHD_NONNULL(1);
|
||||
enum MHD_Bool destroy_after_use)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -2949,7 +2971,7 @@ MHD_action_from_response (struct MHD_Response *response,
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_response_option_v10_only (struct MHD_Response *response)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3023,8 +3045,8 @@ enum MHD_RequestTerminationCode
|
||||
*/
|
||||
typedef void
|
||||
(*MHD_RequestTerminationCallback) (void *cls,
|
||||
enum MHD_RequestTerminationCode toe,
|
||||
void *request_context);
|
||||
enum MHD_RequestTerminationCode toe,
|
||||
void *request_context);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3037,9 +3059,10 @@ typedef void
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_response_option_termination_callback (struct MHD_Response *response,
|
||||
MHD_RequestTerminationCallback termination_cb,
|
||||
void *termination_cb_cls)
|
||||
MHD_NONNULL(1);
|
||||
MHD_RequestTerminationCallback
|
||||
termination_cb,
|
||||
void *termination_cb_cls)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3124,11 +3147,11 @@ typedef void
|
||||
*/
|
||||
_MHD_EXTERN struct MHD_Response *
|
||||
MHD_response_from_callback (enum MHD_HTTP_StatusCode sc,
|
||||
uint64_t size,
|
||||
size_t block_size,
|
||||
MHD_ContentReaderCallback crc,
|
||||
void *crc_cls,
|
||||
MHD_ContentReaderFreeCallback crfc);
|
||||
uint64_t size,
|
||||
size_t block_size,
|
||||
MHD_ContentReaderCallback crc,
|
||||
void *crc_cls,
|
||||
MHD_ContentReaderFreeCallback crfc);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3181,9 +3204,9 @@ enum MHD_ResponseMemoryMode
|
||||
*/
|
||||
_MHD_EXTERN struct MHD_Response *
|
||||
MHD_response_from_buffer (enum MHD_HTTP_StatusCode sc,
|
||||
size_t size,
|
||||
void *buffer,
|
||||
enum MHD_ResponseMemoryMode mode);
|
||||
size_t size,
|
||||
void *buffer,
|
||||
enum MHD_ResponseMemoryMode mode);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3206,9 +3229,9 @@ MHD_response_from_buffer (enum MHD_HTTP_StatusCode sc,
|
||||
*/
|
||||
_MHD_EXTERN struct MHD_Response *
|
||||
MHD_response_from_fd (enum MHD_HTTP_StatusCode sc,
|
||||
int fd,
|
||||
uint64_t offset,
|
||||
uint64_t size);
|
||||
int fd,
|
||||
uint64_t offset,
|
||||
uint64_t size);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3255,9 +3278,9 @@ struct MHD_UpgradeResponseHandle;
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_Bool
|
||||
MHD_upgrade_operation (struct MHD_UpgradeResponseHandle *urh,
|
||||
enum MHD_UpgradeOperation operation,
|
||||
...)
|
||||
MHD_NONNULL(1);
|
||||
enum MHD_UpgradeOperation operation,
|
||||
...)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3349,8 +3372,8 @@ typedef void
|
||||
*/
|
||||
_MHD_EXTERN struct MHD_Response *
|
||||
MHD_response_for_upgrade (MHD_UpgradeHandler upgrade_handler,
|
||||
void *upgrade_handler_cls)
|
||||
MHD_NONNULL(1);
|
||||
void *upgrade_handler_cls)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3364,7 +3387,7 @@ MHD_response_for_upgrade (MHD_UpgradeHandler upgrade_handler,
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_response_queue_for_destroy (struct MHD_Response *response)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3380,8 +3403,8 @@ MHD_response_queue_for_destroy (struct MHD_Response *response)
|
||||
_MHD_EXTERN enum MHD_Bool
|
||||
MHD_response_add_header (struct MHD_Response *response,
|
||||
const char *header,
|
||||
const char *content)
|
||||
MHD_NONNULL(1,2,3);
|
||||
const char *content)
|
||||
MHD_NONNULL (1,2,3);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3398,7 +3421,7 @@ _MHD_EXTERN enum MHD_Bool
|
||||
MHD_response_add_trailer (struct MHD_Response *response,
|
||||
const char *footer,
|
||||
const char *content)
|
||||
MHD_NONNULL(1,2,3);
|
||||
MHD_NONNULL (1,2,3);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3413,8 +3436,8 @@ MHD_response_add_trailer (struct MHD_Response *response,
|
||||
_MHD_EXTERN enum MHD_Bool
|
||||
MHD_response_del_header (struct MHD_Response *response,
|
||||
const char *header,
|
||||
const char *content)
|
||||
MHD_NONNULL(1,2,3);
|
||||
const char *content)
|
||||
MHD_NONNULL (1,2,3);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3430,8 +3453,8 @@ MHD_response_del_header (struct MHD_Response *response,
|
||||
_MHD_EXTERN unsigned int
|
||||
MHD_response_get_headers (struct MHD_Response *response,
|
||||
MHD_KeyValueIterator iterator,
|
||||
void *iterator_cls)
|
||||
MHD_NONNULL(1);
|
||||
void *iterator_cls)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3444,8 +3467,8 @@ MHD_response_get_headers (struct MHD_Response *response,
|
||||
*/
|
||||
_MHD_EXTERN const char *
|
||||
MHD_response_get_header (struct MHD_Response *response,
|
||||
const char *key)
|
||||
MHD_NONNULL(1,2);
|
||||
const char *key)
|
||||
MHD_NONNULL (1,2);
|
||||
|
||||
|
||||
/* ************Upload and PostProcessor functions ********************** */
|
||||
@@ -3480,8 +3503,8 @@ MHD_action_continue (void);
|
||||
*/
|
||||
typedef const struct MHD_Action *
|
||||
(*MHD_UploadCallback) (void *cls,
|
||||
const char *upload_data,
|
||||
size_t *upload_data_size);
|
||||
const char *upload_data,
|
||||
size_t *upload_data_size);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3494,8 +3517,8 @@ typedef const struct MHD_Action *
|
||||
*/
|
||||
_MHD_EXTERN const struct MHD_Action *
|
||||
MHD_action_process_upload (MHD_UploadCallback uc,
|
||||
void *uc_cls)
|
||||
MHD_NONNULL(1);
|
||||
void *uc_cls)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3559,9 +3582,9 @@ typedef const struct MHD_Action *
|
||||
*/
|
||||
_MHD_EXTERN const struct MHD_Action *
|
||||
MHD_action_parse_post (size_t buffer_size,
|
||||
MHD_PostDataIterator iter,
|
||||
void *iter_cls)
|
||||
MHD_NONNULL(2);
|
||||
MHD_PostDataIterator iter,
|
||||
void *iter_cls)
|
||||
MHD_NONNULL (2);
|
||||
|
||||
|
||||
|
||||
@@ -3730,10 +3753,10 @@ union MHD_ConnectionInformation
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_Bool
|
||||
MHD_connection_get_information_sz (struct MHD_Connection *connection,
|
||||
enum MHD_ConnectionInformationType info_type,
|
||||
union MHD_ConnectionInformation *return_value,
|
||||
size_t return_value_size)
|
||||
MHD_NONNULL(1,3);
|
||||
enum MHD_ConnectionInformationType info_type,
|
||||
union MHD_ConnectionInformation *return_value,
|
||||
size_t return_value_size)
|
||||
MHD_NONNULL (1,3);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3750,7 +3773,8 @@ MHD_connection_get_information_sz (struct MHD_Connection *connection,
|
||||
#define MHD_connection_get_information(connection, \
|
||||
info_type, \
|
||||
return_value) \
|
||||
MHD_connection_get_information_sz ((connection),(info_type),(return_value),sizeof(union MHD_ConnectionInformation))
|
||||
MHD_connection_get_information_sz ((connection),(info_type),(return_value), \
|
||||
sizeof(union MHD_ConnectionInformation))
|
||||
|
||||
|
||||
/**
|
||||
@@ -3843,10 +3867,10 @@ enum MHD_RequestInformationType
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_Bool
|
||||
MHD_request_get_information_sz (struct MHD_Request *request,
|
||||
enum MHD_RequestInformationType info_type,
|
||||
union MHD_RequestInformation *return_value,
|
||||
size_t return_value_size)
|
||||
MHD_NONNULL(1,3);
|
||||
enum MHD_RequestInformationType info_type,
|
||||
union MHD_RequestInformation *return_value,
|
||||
size_t return_value_size)
|
||||
MHD_NONNULL (1,3);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3863,7 +3887,8 @@ MHD_request_get_information_sz (struct MHD_Request *request,
|
||||
#define MHD_request_get_information (request, \
|
||||
info_type, \
|
||||
return_value) \
|
||||
MHD_request_get_information_sz ((request), (info_type), (return_value), sizeof(union MHD_RequestInformation))
|
||||
MHD_request_get_information_sz ((request), (info_type), (return_value), \
|
||||
sizeof(union MHD_RequestInformation))
|
||||
|
||||
|
||||
/**
|
||||
@@ -3950,10 +3975,10 @@ union MHD_DaemonInformation
|
||||
*/
|
||||
_MHD_EXTERN enum MHD_Bool
|
||||
MHD_daemon_get_information_sz (struct MHD_Daemon *daemon,
|
||||
enum MHD_DaemonInformationType info_type,
|
||||
union MHD_DaemonInformation *return_value,
|
||||
size_t return_value_size)
|
||||
MHD_NONNULL(1,3);
|
||||
enum MHD_DaemonInformationType info_type,
|
||||
union MHD_DaemonInformation *return_value,
|
||||
size_t return_value_size)
|
||||
MHD_NONNULL (1,3);
|
||||
|
||||
/**
|
||||
* Obtain information about the given daemon.
|
||||
@@ -3969,7 +3994,8 @@ MHD_daemon_get_information_sz (struct MHD_Daemon *daemon,
|
||||
#define MHD_daemon_get_information(daemon, \
|
||||
info_type, \
|
||||
return_value) \
|
||||
MHD_daemon_get_information_sz((daemon), (info_type), (return_value), sizeof(union MHD_DaemonInformation));
|
||||
MHD_daemon_get_information_sz ((daemon), (info_type), (return_value), \
|
||||
sizeof(union MHD_DaemonInformation));
|
||||
|
||||
|
||||
/**
|
||||
@@ -4007,7 +4033,7 @@ typedef void
|
||||
*/
|
||||
_MHD_EXTERN void
|
||||
MHD_set_panic_func (MHD_PanicCallback cb,
|
||||
void *cls);
|
||||
void *cls);
|
||||
|
||||
|
||||
/**
|
||||
@@ -4021,7 +4047,7 @@ MHD_set_panic_func (MHD_PanicCallback cb,
|
||||
*/
|
||||
_MHD_EXTERN size_t
|
||||
MHD_http_unescape (char *val)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -54,9 +54,9 @@ struct MHD_TLS_Plugin
|
||||
{
|
||||
/**
|
||||
* Closure with plugin's internal state, opaque to MHD.
|
||||
*/
|
||||
*/
|
||||
void *cls;
|
||||
|
||||
|
||||
/**
|
||||
* Destroy the plugin, we are done with it.
|
||||
*/
|
||||
@@ -77,9 +77,9 @@ struct MHD_TLS_Plugin
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
(*init_kcp)(void *cls,
|
||||
const char *mem_key,
|
||||
const char *mem_cert,
|
||||
const char *pass);
|
||||
const char *mem_key,
|
||||
const char *mem_cert,
|
||||
const char *pass);
|
||||
|
||||
|
||||
/**
|
||||
@@ -91,7 +91,7 @@ struct MHD_TLS_Plugin
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
(*init_dhparams)(void *cls,
|
||||
const char *dh);
|
||||
const char *dh);
|
||||
|
||||
|
||||
/**
|
||||
@@ -103,7 +103,7 @@ struct MHD_TLS_Plugin
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
(*init_mem_trust)(void *cls,
|
||||
const char *mem_trust);
|
||||
const char *mem_trust);
|
||||
|
||||
|
||||
/**
|
||||
@@ -116,59 +116,59 @@ struct MHD_TLS_Plugin
|
||||
*/
|
||||
struct MHD_TLS_ConnectionState *
|
||||
(*setup_connection)(void *cls,
|
||||
...);
|
||||
...);
|
||||
|
||||
|
||||
enum MHD_Bool
|
||||
(*handshake)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
|
||||
|
||||
enum MHD_Bool
|
||||
(*idle_ready)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
|
||||
|
||||
enum MHD_Bool
|
||||
(*update_event_loop_info)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs,
|
||||
enum MHD_RequestEventLoopInfo *eli);
|
||||
|
||||
struct MHD_TLS_ConnectionState *cs,
|
||||
enum MHD_RequestEventLoopInfo *eli);
|
||||
|
||||
ssize_t
|
||||
(*send)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs,
|
||||
const void *buf,
|
||||
size_t buf_size);
|
||||
struct MHD_TLS_ConnectionState *cs,
|
||||
const void *buf,
|
||||
size_t buf_size);
|
||||
|
||||
|
||||
ssize_t
|
||||
(*recv)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs,
|
||||
void *buf,
|
||||
size_t buf_size);
|
||||
struct MHD_TLS_ConnectionState *cs,
|
||||
void *buf,
|
||||
size_t buf_size);
|
||||
|
||||
|
||||
const char *
|
||||
(*strerror)(void *cls,
|
||||
int ec);
|
||||
int ec);
|
||||
|
||||
enum MHD_Bool
|
||||
(*check_record_pending)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
|
||||
enum MHD_Bool
|
||||
(*shutdown_connection) (void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
(*shutdown_connection)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
|
||||
|
||||
|
||||
void
|
||||
(*teardown_connection)(void *cls,
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
|
||||
struct MHD_TLS_ConnectionState *cs);
|
||||
|
||||
/**
|
||||
* TODO: More functions here....
|
||||
*/
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ typedef struct MHD_TLS_Plugin *
|
||||
*/
|
||||
#define MHD_TLS_INIT(body) \
|
||||
struct MHD_TLS_Plugin * \
|
||||
MHD_TLS_init_ ## MHD_TLS_ABI_VERSION (const char *ciphers) \\
|
||||
MHD_TLS_init_ ## MHD_TLS_ABI_VERSION (const char *ciphers) \ \
|
||||
{ body }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
#if HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#if defined(_WIN32) && ! defined(__CYGWIN__)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
/* Do not include unneeded parts of W32 headers. */
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
@@ -103,28 +103,28 @@
|
||||
#include <ws2tcpip.h>
|
||||
#endif /* _WIN32 && !__CYGWIN__ */
|
||||
|
||||
#if defined(__CYGWIN__) && !defined(_SYS_TYPES_FD_SET)
|
||||
#if defined(__CYGWIN__) && ! defined(_SYS_TYPES_FD_SET)
|
||||
/* Do not define __USE_W32_SOCKETS under Cygwin! */
|
||||
#error Cygwin with winsock fd_set is not supported
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#define sleep(seconds) ((SleepEx((seconds)*1000, 1)==0)?0:(seconds))
|
||||
#define usleep(useconds) ((SleepEx((useconds)/1000, 1)==0)?0:-1)
|
||||
#if defined(_WIN32) && ! defined(__CYGWIN__)
|
||||
#define sleep(seconds) ((SleepEx ((seconds) * 1000, 1)==0) ? 0 : (seconds))
|
||||
#define usleep(useconds) ((SleepEx ((useconds) / 1000, 1)==0) ? 0 : -1)
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_FULL_VER) && !defined (_SSIZE_T_DEFINED)
|
||||
#if defined(_MSC_FULL_VER) && ! defined (_SSIZE_T_DEFINED)
|
||||
#define _SSIZE_T_DEFINED
|
||||
typedef intptr_t ssize_t;
|
||||
#endif /* !_SSIZE_T_DEFINED */
|
||||
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
#if ! defined(_WIN32) || defined(__CYGWIN__)
|
||||
typedef time_t _MHD_TIMEVAL_TV_SEC_TYPE;
|
||||
#else /* _WIN32 && ! __CYGWIN__ */
|
||||
typedef long _MHD_TIMEVAL_TV_SEC_TYPE;
|
||||
#endif /* _WIN32 && ! __CYGWIN__ */
|
||||
|
||||
#if !defined(IPPROTO_IPV6) && defined(_MSC_FULL_VER) && _WIN32_WINNT >= 0x0501
|
||||
#if ! defined(IPPROTO_IPV6) && defined(_MSC_FULL_VER) && _WIN32_WINNT >= 0x0501
|
||||
/* VC use IPPROTO_IPV6 as part of enum */
|
||||
#define IPPROTO_IPV6 IPPROTO_IPV6
|
||||
#endif
|
||||
|
||||
@@ -35,11 +35,11 @@
|
||||
*/
|
||||
static enum MHD_StatusCode
|
||||
cont_action (void *cls,
|
||||
struct MHD_Request *request)
|
||||
struct MHD_Request *request)
|
||||
{
|
||||
(void) cls;
|
||||
(void) request;
|
||||
/* not sure yet, but this function body may
|
||||
/* not sure yet, but this function body may
|
||||
just legitimately stay empty... */
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
*/
|
||||
static enum MHD_StatusCode
|
||||
response_action (void *cls,
|
||||
struct MHD_Request *request)
|
||||
struct MHD_Request *request)
|
||||
{
|
||||
struct MHD_Response *response = cls;
|
||||
struct MHD_Daemon *daemon = request->daemon;
|
||||
@@ -49,14 +49,15 @@ response_action (void *cls,
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
if ( (NULL != response->upgrade_handler) &&
|
||||
daemon->disallow_upgrade )
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_UPGRADE_ON_DAEMON_WITH_UPGRADE_DISALLOWED,
|
||||
_("Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_UPGRADE_ON_DAEMON_WITH_UPGRADE_DISALLOWED,
|
||||
_ (
|
||||
"Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"));
|
||||
#endif
|
||||
return MHD_SC_UPGRADE_ON_DAEMON_WITH_UPGRADE_DISALLOWED;
|
||||
}
|
||||
return MHD_SC_UPGRADE_ON_DAEMON_WITH_UPGRADE_DISALLOWED;
|
||||
}
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
request->response = response;
|
||||
#if defined(_MHD_HAVE_SENDFILE)
|
||||
@@ -74,21 +75,21 @@ response_action (void *cls,
|
||||
(MHD_HTTP_OK > response->status_code) ||
|
||||
(MHD_HTTP_NO_CONTENT == response->status_code) ||
|
||||
(MHD_HTTP_NOT_MODIFIED == response->status_code) )
|
||||
{
|
||||
/* if this is a "HEAD" request, or a status code for
|
||||
which a body is not allowed, pretend that we
|
||||
have already sent the full message body. */
|
||||
request->response_write_position = response->total_size;
|
||||
}
|
||||
{
|
||||
/* if this is a "HEAD" request, or a status code for
|
||||
which a body is not allowed, pretend that we
|
||||
have already sent the full message body. */
|
||||
request->response_write_position = response->total_size;
|
||||
}
|
||||
if ( (MHD_REQUEST_HEADERS_PROCESSED == request->state) &&
|
||||
( (MHD_METHOD_POST == request->method) ||
|
||||
(MHD_METHOD_PUT == request->method) ) )
|
||||
{
|
||||
/* response was queued "early", refuse to read body / footers or
|
||||
further requests! */
|
||||
request->connection->read_closed = true;
|
||||
request->state = MHD_REQUEST_FOOTERS_RECEIVED;
|
||||
}
|
||||
(MHD_METHOD_PUT == request->method) ) )
|
||||
{
|
||||
/* response was queued "early", refuse to read body / footers or
|
||||
further requests! */
|
||||
request->connection->read_closed = true;
|
||||
request->state = MHD_REQUEST_FOOTERS_RECEIVED;
|
||||
}
|
||||
if (! request->in_idle)
|
||||
(void) MHD_request_handle_idle_ (request);
|
||||
return MHD_SC_OK;
|
||||
@@ -114,16 +115,16 @@ response_action (void *cls,
|
||||
*/
|
||||
_MHD_EXTERN const struct MHD_Action *
|
||||
MHD_action_from_response (struct MHD_Response *response,
|
||||
enum MHD_Bool destroy_after_use)
|
||||
enum MHD_Bool destroy_after_use)
|
||||
{
|
||||
response->action.action = &response_action;
|
||||
response->action.action_cls = response;
|
||||
if (! destroy_after_use)
|
||||
{
|
||||
MHD_mutex_lock_chk_ (&response->mutex);
|
||||
response->reference_count++;
|
||||
MHD_mutex_unlock_chk_ (&response->mutex);
|
||||
}
|
||||
{
|
||||
MHD_mutex_lock_chk_ (&response->mutex);
|
||||
response->reference_count++;
|
||||
MHD_mutex_unlock_chk_ (&response->mutex);
|
||||
}
|
||||
return &response->action;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,8 +52,8 @@
|
||||
*/
|
||||
const struct MHD_Action *
|
||||
MHD_action_parse_post (size_t buffer_size,
|
||||
MHD_PostDataIterator iter,
|
||||
void *iter_cls)
|
||||
MHD_PostDataIterator iter,
|
||||
void *iter_cls)
|
||||
{
|
||||
return NULL; /* not yet implemented */
|
||||
}
|
||||
|
||||
@@ -49,13 +49,13 @@ struct UploadAction
|
||||
*
|
||||
* @param cls the `struct UploadAction` with the
|
||||
* function we are to call for upload data
|
||||
* @param request the request for which we are to process
|
||||
* @param request the request for which we are to process
|
||||
* upload data
|
||||
* @return #MHD_SC_OK on success
|
||||
*/
|
||||
static enum MHD_StatusCode
|
||||
upload_action (void *cls,
|
||||
struct MHD_Request *request)
|
||||
struct MHD_Request *request)
|
||||
{
|
||||
struct UploadAction *ua = cls;
|
||||
|
||||
@@ -75,7 +75,7 @@ upload_action (void *cls,
|
||||
*/
|
||||
const struct MHD_Action *
|
||||
MHD_action_process_upload (MHD_UploadCallback uc,
|
||||
void *uc_cls)
|
||||
void *uc_cls)
|
||||
{
|
||||
struct UploadAction *ua;
|
||||
|
||||
@@ -90,5 +90,3 @@ MHD_action_process_upload (MHD_UploadCallback uc,
|
||||
|
||||
|
||||
/* end of action_process_upload.c */
|
||||
|
||||
|
||||
|
||||
+35
-35
@@ -35,7 +35,7 @@
|
||||
*/
|
||||
static enum MHD_StatusCode
|
||||
suspend_action (void *cls,
|
||||
struct MHD_Request *request)
|
||||
struct MHD_Request *request)
|
||||
{
|
||||
(void) cls;
|
||||
struct MHD_Connection *connection = request->connection;
|
||||
@@ -43,24 +43,24 @@ suspend_action (void *cls,
|
||||
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
if (connection->resuming)
|
||||
{
|
||||
/* suspending again while we didn't even complete resuming yet */
|
||||
connection->resuming = false;
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
{
|
||||
/* suspending again while we didn't even complete resuming yet */
|
||||
connection->resuming = false;
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
if (daemon->threading_mode != MHD_TM_THREAD_PER_CONNECTION)
|
||||
{
|
||||
if (connection->connection_timeout ==
|
||||
daemon->connection_default_timeout)
|
||||
XDLL_remove (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
else
|
||||
XDLL_remove (daemon->manual_timeout_head,
|
||||
daemon->manual_timeout_tail,
|
||||
connection);
|
||||
}
|
||||
{
|
||||
if (connection->connection_timeout ==
|
||||
daemon->connection_default_timeout)
|
||||
XDLL_remove (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
else
|
||||
XDLL_remove (daemon->manual_timeout_head,
|
||||
daemon->manual_timeout_tail,
|
||||
connection);
|
||||
}
|
||||
DLL_remove (daemon->connections_head,
|
||||
daemon->connections_tail,
|
||||
connection);
|
||||
@@ -71,25 +71,25 @@ suspend_action (void *cls,
|
||||
connection->suspended = true;
|
||||
#ifdef EPOLL_SUPPORT
|
||||
if (MHD_ELS_EPOLL == daemon->event_loop_syscall)
|
||||
{
|
||||
if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
|
||||
{
|
||||
if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
|
||||
{
|
||||
EDLL_remove (daemon->eready_head,
|
||||
daemon->eready_tail,
|
||||
connection);
|
||||
connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
|
||||
}
|
||||
if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
|
||||
{
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_DEL,
|
||||
connection->socket_fd,
|
||||
NULL))
|
||||
MHD_PANIC (_("Failed to remove FD from epoll set\n"));
|
||||
connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
|
||||
}
|
||||
connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
|
||||
EDLL_remove (daemon->eready_head,
|
||||
daemon->eready_tail,
|
||||
connection);
|
||||
connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
|
||||
}
|
||||
if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
|
||||
{
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_DEL,
|
||||
connection->socket_fd,
|
||||
NULL))
|
||||
MHD_PANIC (_ ("Failed to remove FD from epoll set\n"));
|
||||
connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
|
||||
}
|
||||
connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
|
||||
}
|
||||
#endif
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
return MHD_SC_OK;
|
||||
|
||||
+28
-27
@@ -9,45 +9,46 @@
|
||||
#include "base64.h"
|
||||
|
||||
static const char base64_digits[] =
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
|
||||
0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
|
||||
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26,
|
||||
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
|
||||
45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
|
||||
0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
|
||||
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26,
|
||||
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
|
||||
45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
|
||||
char *
|
||||
BASE64Decode(const char* src)
|
||||
BASE64Decode (const char*src)
|
||||
{
|
||||
size_t in_len = strlen (src);
|
||||
char* dest;
|
||||
char* result;
|
||||
char*dest;
|
||||
char*result;
|
||||
|
||||
if (in_len % 4)
|
||||
{
|
||||
/* Wrong base64 string length */
|
||||
return NULL;
|
||||
}
|
||||
result = dest = malloc(in_len / 4 * 3 + 1);
|
||||
{
|
||||
/* Wrong base64 string length */
|
||||
return NULL;
|
||||
}
|
||||
result = dest = malloc (in_len / 4 * 3 + 1);
|
||||
if (NULL == result)
|
||||
return NULL; /* out of memory */
|
||||
while (*src) {
|
||||
char a = base64_digits[(unsigned char)*(src++)];
|
||||
char b = base64_digits[(unsigned char)*(src++)];
|
||||
char c = base64_digits[(unsigned char)*(src++)];
|
||||
char d = base64_digits[(unsigned char)*(src++)];
|
||||
while (*src)
|
||||
{
|
||||
char a = base64_digits[(unsigned char) *(src++)];
|
||||
char b = base64_digits[(unsigned char) *(src++)];
|
||||
char c = base64_digits[(unsigned char) *(src++)];
|
||||
char d = base64_digits[(unsigned char) *(src++)];
|
||||
*(dest++) = (a << 2) | ((b & 0x30) >> 4);
|
||||
if (c == (char)-1)
|
||||
if (c == (char) -1)
|
||||
break;
|
||||
*(dest++) = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2);
|
||||
if (d == (char)-1)
|
||||
if (d == (char) -1)
|
||||
break;
|
||||
*(dest++) = ((c & 0x03) << 6) | d;
|
||||
}
|
||||
|
||||
+1
-1
@@ -12,6 +12,6 @@
|
||||
#include "platform.h"
|
||||
|
||||
char *
|
||||
BASE64Decode(const char* src);
|
||||
BASE64Decode (const char*src);
|
||||
|
||||
#endif /* !BASE64_H */
|
||||
|
||||
+637
-627
@@ -53,14 +53,14 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
|
||||
with the socket; */
|
||||
if ( (NULL != daemon->tls_api) &&
|
||||
(MHD_ELS_POLL != daemon->event_loop_syscall) )
|
||||
{
|
||||
MHD_daemon_upgrade_connection_with_select_ (con);
|
||||
}
|
||||
{
|
||||
MHD_daemon_upgrade_connection_with_select_ (con);
|
||||
}
|
||||
#ifdef HAVE_POLL
|
||||
else if (NULL != daemon->tls_api)
|
||||
{
|
||||
MHD_daemon_upgrade_connection_with_poll_ (con);
|
||||
}
|
||||
{
|
||||
MHD_daemon_upgrade_connection_with_poll_ (con);
|
||||
}
|
||||
#endif
|
||||
/* end HTTPS */
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
@@ -111,342 +111,344 @@ thread_main_handle_connection (void *data)
|
||||
#endif /* ! HAVE_POLL */
|
||||
bool was_suspended = false;
|
||||
|
||||
MHD_thread_init_(&con->pid);
|
||||
MHD_thread_init_ (&con->pid);
|
||||
|
||||
while ( (! daemon->shutdown) &&
|
||||
(MHD_REQUEST_CLOSED != con->request.state) )
|
||||
{
|
||||
const time_t timeout = daemon->connection_default_timeout;
|
||||
(MHD_REQUEST_CLOSED != con->request.state) )
|
||||
{
|
||||
const time_t timeout = daemon->connection_default_timeout;
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
struct MHD_UpgradeResponseHandle * const urh = con->request.urh;
|
||||
struct MHD_UpgradeResponseHandle *const urh = con->request.urh;
|
||||
#else /* ! UPGRADE_SUPPORT */
|
||||
static const void * const urh = NULL;
|
||||
static const void *const urh = NULL;
|
||||
#endif /* ! UPGRADE_SUPPORT */
|
||||
|
||||
if ( (con->suspended) &&
|
||||
(NULL == urh) )
|
||||
if ( (con->suspended) &&
|
||||
(NULL == urh) )
|
||||
{
|
||||
/* Connection was suspended, wait for resume. */
|
||||
was_suspended = true;
|
||||
if (! use_poll)
|
||||
{
|
||||
FD_ZERO (&rs);
|
||||
if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
|
||||
&rs,
|
||||
NULL,
|
||||
FD_SETSIZE))
|
||||
{
|
||||
/* Connection was suspended, wait for resume. */
|
||||
was_suspended = true;
|
||||
if (! use_poll)
|
||||
{
|
||||
FD_ZERO (&rs);
|
||||
if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
|
||||
&rs,
|
||||
NULL,
|
||||
FD_SETSIZE))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
|
||||
_("Failed to add FD to fd_set\n"));
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
|
||||
_ ("Failed to add FD to fd_set\n"));
|
||||
#endif
|
||||
goto exit;
|
||||
}
|
||||
if (0 > MHD_SYS_select_ (MHD_itc_r_fd_ (daemon->itc) + 1,
|
||||
&rs,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL))
|
||||
{
|
||||
const int err = MHD_socket_get_error_();
|
||||
|
||||
if (MHD_SCKT_ERR_IS_EINTR_(err))
|
||||
continue;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_UNEXPECTED_SELECT_ERROR,
|
||||
_("Error during select (%d): `%s'\n"),
|
||||
err,
|
||||
MHD_socket_strerr_ (err));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_POLL
|
||||
else /* use_poll */
|
||||
{
|
||||
p[0].events = POLLIN;
|
||||
p[0].fd = MHD_itc_r_fd_ (daemon->itc);
|
||||
p[0].revents = 0;
|
||||
if (0 > MHD_sys_poll_ (p,
|
||||
1,
|
||||
-1))
|
||||
{
|
||||
if (MHD_SCKT_LAST_ERR_IS_(MHD_SCKT_EINTR_))
|
||||
continue;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_UNEXPECTED_POLL_ERROR,
|
||||
_("Error during poll: `%s'\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_POLL */
|
||||
MHD_itc_clear_ (daemon->itc);
|
||||
continue; /* Check again for resume. */
|
||||
} /* End of "suspended" branch. */
|
||||
|
||||
if (was_suspended)
|
||||
{
|
||||
MHD_connection_update_last_activity_ (con); /* Reset timeout timer. */
|
||||
/* Process response queued during suspend and update states. */
|
||||
MHD_request_handle_idle_ (&con->request);
|
||||
was_suspended = false;
|
||||
goto exit;
|
||||
}
|
||||
if (0 > MHD_SYS_select_ (MHD_itc_r_fd_ (daemon->itc) + 1,
|
||||
&rs,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL))
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
|
||||
tvp = NULL;
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
continue;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_UNEXPECTED_SELECT_ERROR,
|
||||
_ ("Error during select (%d): `%s'\n"),
|
||||
err,
|
||||
MHD_socket_strerr_ (err));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_POLL
|
||||
else /* use_poll */
|
||||
{
|
||||
p[0].events = POLLIN;
|
||||
p[0].fd = MHD_itc_r_fd_ (daemon->itc);
|
||||
p[0].revents = 0;
|
||||
if (0 > MHD_sys_poll_ (p,
|
||||
1,
|
||||
-1))
|
||||
{
|
||||
if (MHD_SCKT_LAST_ERR_IS_ (MHD_SCKT_EINTR_))
|
||||
continue;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_UNEXPECTED_POLL_ERROR,
|
||||
_ ("Error during poll: `%s'\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_POLL */
|
||||
MHD_itc_clear_ (daemon->itc);
|
||||
continue; /* Check again for resume. */
|
||||
} /* End of "suspended" branch. */
|
||||
|
||||
if ( (MHD_EVENT_LOOP_INFO_BLOCK == con->request.event_loop_info)
|
||||
if (was_suspended)
|
||||
{
|
||||
MHD_connection_update_last_activity_ (con); /* Reset timeout timer. */
|
||||
/* Process response queued during suspend and update states. */
|
||||
MHD_request_handle_idle_ (&con->request);
|
||||
was_suspended = false;
|
||||
}
|
||||
|
||||
tvp = NULL;
|
||||
|
||||
if ( (MHD_EVENT_LOOP_INFO_BLOCK == con->request.event_loop_info)
|
||||
#ifdef HTTPS_SUPPORT
|
||||
|| ( (con->tls_read_ready) &&
|
||||
(MHD_EVENT_LOOP_INFO_READ == con->request.event_loop_info) )
|
||||
|| ( (con->tls_read_ready) &&
|
||||
(MHD_EVENT_LOOP_INFO_READ == con->request.event_loop_info) )
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
)
|
||||
{
|
||||
/* do not block: more data may be inside of TLS buffers waiting or
|
||||
* application must provide response data */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
tvp = &tv;
|
||||
}
|
||||
if ( (NULL == tvp) &&
|
||||
(timeout > 0) )
|
||||
{
|
||||
now = MHD_monotonic_sec_counter();
|
||||
if (now - con->last_activity > timeout)
|
||||
tv.tv_sec = 0;
|
||||
else
|
||||
{
|
||||
const time_t seconds_left = timeout - (now - con->last_activity);
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
tv.tv_sec = seconds_left;
|
||||
#else /* _WIN32 && !__CYGWIN__ */
|
||||
if (seconds_left > TIMEVAL_TV_SEC_MAX)
|
||||
tv.tv_sec = TIMEVAL_TV_SEC_MAX;
|
||||
else
|
||||
tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) seconds_left;
|
||||
#endif /* _WIN32 && ! __CYGWIN__ */
|
||||
}
|
||||
tv.tv_usec = 0;
|
||||
tvp = &tv;
|
||||
}
|
||||
if (! use_poll)
|
||||
{
|
||||
/* use select */
|
||||
bool err_state = false;
|
||||
|
||||
FD_ZERO (&rs);
|
||||
FD_ZERO (&ws);
|
||||
FD_ZERO (&es);
|
||||
maxsock = MHD_INVALID_SOCKET;
|
||||
switch (con->request.event_loop_info)
|
||||
{
|
||||
case MHD_EVENT_LOOP_INFO_READ:
|
||||
if (! MHD_add_to_fd_set_ (con->socket_fd,
|
||||
&rs,
|
||||
&maxsock,
|
||||
FD_SETSIZE))
|
||||
err_state = true;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_WRITE:
|
||||
if (! MHD_add_to_fd_set_ (con->socket_fd,
|
||||
&ws,
|
||||
&maxsock,
|
||||
FD_SETSIZE))
|
||||
err_state = true;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_BLOCK:
|
||||
if (! MHD_add_to_fd_set_ (con->socket_fd,
|
||||
&es,
|
||||
&maxsock,
|
||||
FD_SETSIZE))
|
||||
err_state = true;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_CLEANUP:
|
||||
/* how did we get here!? */
|
||||
goto exit;
|
||||
}
|
||||
#if WINDOWS
|
||||
if (MHD_ITC_IS_VALID_(daemon->itc) )
|
||||
{
|
||||
if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
|
||||
&rs,
|
||||
&maxsock,
|
||||
FD_SETSIZE))
|
||||
err_state = 1;
|
||||
}
|
||||
#endif
|
||||
if (err_state)
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
|
||||
_("Failed to add FD to fd_set\n"));
|
||||
#endif
|
||||
goto exit;
|
||||
}
|
||||
|
||||
num_ready = MHD_SYS_select_ (maxsock + 1,
|
||||
&rs,
|
||||
&ws,
|
||||
&es,
|
||||
tvp);
|
||||
if (num_ready < 0)
|
||||
{
|
||||
const int err = MHD_socket_get_error_();
|
||||
|
||||
if (MHD_SCKT_ERR_IS_EINTR_(err))
|
||||
continue;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_UNEXPECTED_SELECT_ERROR,
|
||||
_("Error during select (%d): `%s'\n"),
|
||||
err,
|
||||
MHD_socket_strerr_ (err));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#if WINDOWS
|
||||
/* Clear ITC before other processing so additional
|
||||
* signals will trigger select() again */
|
||||
if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
|
||||
(FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
|
||||
&rs)) )
|
||||
MHD_itc_clear_ (daemon->itc);
|
||||
#endif
|
||||
if (MHD_NO ==
|
||||
MHD_connection_call_handlers_ (con,
|
||||
FD_ISSET (con->socket_fd,
|
||||
&rs),
|
||||
FD_ISSET (con->socket_fd,
|
||||
&ws),
|
||||
FD_ISSET (con->socket_fd,
|
||||
&es)) )
|
||||
goto exit;
|
||||
}
|
||||
#ifdef HAVE_POLL
|
||||
{
|
||||
/* do not block: more data may be inside of TLS buffers waiting or
|
||||
* application must provide response data */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
tvp = &tv;
|
||||
}
|
||||
if ( (NULL == tvp) &&
|
||||
(timeout > 0) )
|
||||
{
|
||||
now = MHD_monotonic_sec_counter ();
|
||||
if (now - con->last_activity > timeout)
|
||||
tv.tv_sec = 0;
|
||||
else
|
||||
{
|
||||
/* use poll */
|
||||
memset (&p,
|
||||
0,
|
||||
sizeof (p));
|
||||
p[0].fd = con->socket_fd;
|
||||
switch (con->request.event_loop_info)
|
||||
{
|
||||
case MHD_EVENT_LOOP_INFO_READ:
|
||||
p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_WRITE:
|
||||
p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_BLOCK:
|
||||
p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_CLEANUP:
|
||||
/* how did we get here!? */
|
||||
goto exit;
|
||||
}
|
||||
{
|
||||
const time_t seconds_left = timeout - (now - con->last_activity);
|
||||
#if ! defined(_WIN32) || defined(__CYGWIN__)
|
||||
tv.tv_sec = seconds_left;
|
||||
#else /* _WIN32 && !__CYGWIN__ */
|
||||
if (seconds_left > TIMEVAL_TV_SEC_MAX)
|
||||
tv.tv_sec = TIMEVAL_TV_SEC_MAX;
|
||||
else
|
||||
tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) seconds_left;
|
||||
#endif /* _WIN32 && ! __CYGWIN__ */
|
||||
}
|
||||
tv.tv_usec = 0;
|
||||
tvp = &tv;
|
||||
}
|
||||
if (! use_poll)
|
||||
{
|
||||
/* use select */
|
||||
bool err_state = false;
|
||||
|
||||
FD_ZERO (&rs);
|
||||
FD_ZERO (&ws);
|
||||
FD_ZERO (&es);
|
||||
maxsock = MHD_INVALID_SOCKET;
|
||||
switch (con->request.event_loop_info)
|
||||
{
|
||||
case MHD_EVENT_LOOP_INFO_READ:
|
||||
if (! MHD_add_to_fd_set_ (con->socket_fd,
|
||||
&rs,
|
||||
&maxsock,
|
||||
FD_SETSIZE))
|
||||
err_state = true;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_WRITE:
|
||||
if (! MHD_add_to_fd_set_ (con->socket_fd,
|
||||
&ws,
|
||||
&maxsock,
|
||||
FD_SETSIZE))
|
||||
err_state = true;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_BLOCK:
|
||||
if (! MHD_add_to_fd_set_ (con->socket_fd,
|
||||
&es,
|
||||
&maxsock,
|
||||
FD_SETSIZE))
|
||||
err_state = true;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_CLEANUP:
|
||||
/* how did we get here!? */
|
||||
goto exit;
|
||||
}
|
||||
#if WINDOWS
|
||||
extra_slot = 0;
|
||||
if (MHD_ITC_IS_VALID_(daemon->itc))
|
||||
{
|
||||
p[1].events |= POLLIN;
|
||||
p[1].fd = MHD_itc_r_fd_ (daemon->itc);
|
||||
p[1].revents = 0;
|
||||
extra_slot = 1;
|
||||
}
|
||||
if (MHD_ITC_IS_VALID_ (daemon->itc) )
|
||||
{
|
||||
if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
|
||||
&rs,
|
||||
&maxsock,
|
||||
FD_SETSIZE))
|
||||
err_state = 1;
|
||||
}
|
||||
#endif
|
||||
if (MHD_sys_poll_ (p,
|
||||
#if WINDOWS
|
||||
1 + extra_slot,
|
||||
#else
|
||||
1,
|
||||
#endif
|
||||
(NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
|
||||
{
|
||||
if (MHD_SCKT_LAST_ERR_IS_(MHD_SCKT_EINTR_))
|
||||
continue;
|
||||
if (err_state)
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_UNEXPECTED_POLL_ERROR,
|
||||
_("Error during poll: `%s'\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
|
||||
_ ("Failed to add FD to fd_set\n"));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
goto exit;
|
||||
}
|
||||
|
||||
num_ready = MHD_SYS_select_ (maxsock + 1,
|
||||
&rs,
|
||||
&ws,
|
||||
&es,
|
||||
tvp);
|
||||
if (num_ready < 0)
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
continue;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_UNEXPECTED_SELECT_ERROR,
|
||||
_ ("Error during select (%d): `%s'\n"),
|
||||
err,
|
||||
MHD_socket_strerr_ (err));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#if WINDOWS
|
||||
/* Clear ITC before other processing so additional
|
||||
* signals will trigger poll() again */
|
||||
if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
|
||||
(0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
|
||||
MHD_itc_clear_ (daemon->itc);
|
||||
/* Clear ITC before other processing so additional
|
||||
* signals will trigger select() again */
|
||||
if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
|
||||
(FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
|
||||
&rs)) )
|
||||
MHD_itc_clear_ (daemon->itc);
|
||||
#endif
|
||||
if (MHD_NO ==
|
||||
MHD_connection_call_handlers_ (con,
|
||||
0 != (p[0].revents & POLLIN),
|
||||
0 != (p[0].revents & POLLOUT),
|
||||
0 != (p[0].revents & (POLLERR | MHD_POLL_REVENTS_ERR_DISC))))
|
||||
goto exit;
|
||||
}
|
||||
if (MHD_NO ==
|
||||
MHD_connection_call_handlers_ (con,
|
||||
FD_ISSET (con->socket_fd,
|
||||
&rs),
|
||||
FD_ISSET (con->socket_fd,
|
||||
&ws),
|
||||
FD_ISSET (con->socket_fd,
|
||||
&es)) )
|
||||
goto exit;
|
||||
}
|
||||
#ifdef HAVE_POLL
|
||||
else
|
||||
{
|
||||
/* use poll */
|
||||
memset (&p,
|
||||
0,
|
||||
sizeof (p));
|
||||
p[0].fd = con->socket_fd;
|
||||
switch (con->request.event_loop_info)
|
||||
{
|
||||
case MHD_EVENT_LOOP_INFO_READ:
|
||||
p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_WRITE:
|
||||
p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_BLOCK:
|
||||
p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_CLEANUP:
|
||||
/* how did we get here!? */
|
||||
goto exit;
|
||||
}
|
||||
#if WINDOWS
|
||||
extra_slot = 0;
|
||||
if (MHD_ITC_IS_VALID_ (daemon->itc))
|
||||
{
|
||||
p[1].events |= POLLIN;
|
||||
p[1].fd = MHD_itc_r_fd_ (daemon->itc);
|
||||
p[1].revents = 0;
|
||||
extra_slot = 1;
|
||||
}
|
||||
#endif
|
||||
if (MHD_sys_poll_ (p,
|
||||
#if WINDOWS
|
||||
1 + extra_slot,
|
||||
#else
|
||||
1,
|
||||
#endif
|
||||
(NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
|
||||
{
|
||||
if (MHD_SCKT_LAST_ERR_IS_ (MHD_SCKT_EINTR_))
|
||||
continue;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_UNEXPECTED_POLL_ERROR,
|
||||
_ ("Error during poll: `%s'\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#if WINDOWS
|
||||
/* Clear ITC before other processing so additional
|
||||
* signals will trigger poll() again */
|
||||
if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
|
||||
(0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
|
||||
MHD_itc_clear_ (daemon->itc);
|
||||
#endif
|
||||
if (MHD_NO ==
|
||||
MHD_connection_call_handlers_ (con,
|
||||
(0 != (p[0].revents & POLLIN)),
|
||||
(0 != (p[0].revents & POLLOUT)),
|
||||
(0 != (p[0].revents & (POLLERR
|
||||
|
|
||||
MHD_POLL_REVENTS_ERR_DISC))) ))
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
if (MHD_REQUEST_UPGRADE == con->request.state)
|
||||
{
|
||||
/* Normal HTTP processing is finished,
|
||||
* notify application. */
|
||||
if (NULL != con->request.response->termination_cb)
|
||||
con->request.response->termination_cb
|
||||
(con->request.response->termination_cb_cls,
|
||||
MHD_REQUEST_TERMINATED_COMPLETED_OK,
|
||||
con->request.client_context);
|
||||
thread_main_connection_upgrade (con);
|
||||
/* MHD_connection_finish_forward_() was called by thread_main_connection_upgrade(). */
|
||||
if (MHD_REQUEST_UPGRADE == con->request.state)
|
||||
{
|
||||
/* Normal HTTP processing is finished,
|
||||
* notify application. */
|
||||
if (NULL != con->request.response->termination_cb)
|
||||
con->request.response->termination_cb
|
||||
(con->request.response->termination_cb_cls,
|
||||
MHD_REQUEST_TERMINATED_COMPLETED_OK,
|
||||
con->request.client_context);
|
||||
thread_main_connection_upgrade (con);
|
||||
/* MHD_connection_finish_forward_() was called by thread_main_connection_upgrade(). */
|
||||
|
||||
/* "Upgraded" data will not be used in this thread from this point. */
|
||||
con->request.urh->clean_ready = true;
|
||||
/* If 'urh->was_closed' set to true, connection will be
|
||||
* moved immediately to cleanup list. Otherwise connection
|
||||
* will stay in suspended list until 'urh' will be marked
|
||||
* with 'was_closed' by application. */
|
||||
MHD_request_resume (&con->request);
|
||||
/* "Upgraded" data will not be used in this thread from this point. */
|
||||
con->request.urh->clean_ready = true;
|
||||
/* If 'urh->was_closed' set to true, connection will be
|
||||
* moved immediately to cleanup list. Otherwise connection
|
||||
* will stay in suspended list until 'urh' will be marked
|
||||
* with 'was_closed' by application. */
|
||||
MHD_request_resume (&con->request);
|
||||
|
||||
/* skip usual clean up */
|
||||
return (MHD_THRD_RTRN_TYPE_) 0;
|
||||
}
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
/* skip usual clean up */
|
||||
return (MHD_THRD_RTRN_TYPE_) 0;
|
||||
}
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
}
|
||||
#if DEBUG_CLOSE
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_THREAD_TERMINATING,
|
||||
_("Processing thread terminating. Closing connection\n"));
|
||||
_ ("Processing thread terminating. Closing connection\n"));
|
||||
#endif
|
||||
#endif
|
||||
if (MHD_REQUEST_CLOSED != con->request.state)
|
||||
MHD_connection_close_ (con,
|
||||
(daemon->shutdown) ?
|
||||
MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN:
|
||||
MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN :
|
||||
MHD_REQUEST_TERMINATED_WITH_ERROR);
|
||||
MHD_request_handle_idle_ (&con->request);
|
||||
exit:
|
||||
if (NULL != con->request.response)
|
||||
{
|
||||
MHD_response_queue_for_destroy (con->request.response);
|
||||
con->request.response = NULL;
|
||||
}
|
||||
{
|
||||
MHD_response_queue_for_destroy (con->request.response);
|
||||
con->request.response = NULL;
|
||||
}
|
||||
|
||||
if (MHD_INVALID_SOCKET != con->socket_fd)
|
||||
{
|
||||
shutdown (con->socket_fd,
|
||||
SHUT_WR);
|
||||
/* 'socket_fd' can be used in other thread to signal shutdown.
|
||||
* To avoid data races, do not close socket here. Daemon will
|
||||
* use more connections only after cleanup anyway. */
|
||||
}
|
||||
{
|
||||
shutdown (con->socket_fd,
|
||||
SHUT_WR);
|
||||
/* 'socket_fd' can be used in other thread to signal shutdown.
|
||||
* To avoid data races, do not close socket here. Daemon will
|
||||
* use more connections only after cleanup anyway. */
|
||||
}
|
||||
return (MHD_THRD_RTRN_TYPE_) 0;
|
||||
}
|
||||
|
||||
@@ -469,9 +471,9 @@ recv_param_adapter (struct MHD_Connection *connection,
|
||||
|
||||
if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
|
||||
(MHD_REQUEST_CLOSED == connection->request.state) )
|
||||
{
|
||||
return MHD_ERR_NOTCONN_;
|
||||
}
|
||||
{
|
||||
return MHD_ERR_NOTCONN_;
|
||||
}
|
||||
if (i > MHD_SCKT_SEND_MAX_SIZE_)
|
||||
i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
|
||||
|
||||
@@ -479,25 +481,25 @@ recv_param_adapter (struct MHD_Connection *connection,
|
||||
other,
|
||||
i);
|
||||
if (0 > ret)
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
|
||||
{
|
||||
#ifdef EPOLL_SUPPORT
|
||||
/* Got EAGAIN --- no longer read-ready */
|
||||
connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
|
||||
/* Got EAGAIN --- no longer read-ready */
|
||||
connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
|
||||
#endif /* EPOLL_SUPPORT */
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
return MHD_ERR_AGAIN_;
|
||||
if (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_ECONNRESET_))
|
||||
return MHD_ERR_CONNRESET_;
|
||||
/* Treat any other error as hard error. */
|
||||
return MHD_ERR_NOTCONN_;
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
return MHD_ERR_AGAIN_;
|
||||
if (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_ECONNRESET_))
|
||||
return MHD_ERR_CONNRESET_;
|
||||
/* Treat any other error as hard error. */
|
||||
return MHD_ERR_NOTCONN_;
|
||||
}
|
||||
#ifdef EPOLL_SUPPORT
|
||||
else if (i > (size_t)ret)
|
||||
else if (i > (size_t) ret)
|
||||
connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
|
||||
#endif /* EPOLL_SUPPORT */
|
||||
return ret;
|
||||
@@ -522,9 +524,9 @@ send_param_adapter (struct MHD_Connection *connection,
|
||||
|
||||
if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
|
||||
(MHD_REQUEST_CLOSED == connection->request.state) )
|
||||
{
|
||||
return MHD_ERR_NOTCONN_;
|
||||
}
|
||||
{
|
||||
return MHD_ERR_NOTCONN_;
|
||||
}
|
||||
if (i > MHD_SCKT_SEND_MAX_SIZE_)
|
||||
i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
|
||||
|
||||
@@ -532,26 +534,26 @@ send_param_adapter (struct MHD_Connection *connection,
|
||||
other,
|
||||
i);
|
||||
if (0 > ret)
|
||||
{
|
||||
const int err = MHD_socket_get_error_();
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
|
||||
if (MHD_SCKT_ERR_IS_EAGAIN_(err))
|
||||
{
|
||||
if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
|
||||
{
|
||||
#ifdef EPOLL_SUPPORT
|
||||
/* EAGAIN --- no longer write-ready */
|
||||
connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
|
||||
/* EAGAIN --- no longer write-ready */
|
||||
connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
|
||||
#endif /* EPOLL_SUPPORT */
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
return MHD_ERR_AGAIN_;
|
||||
if (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_ECONNRESET_))
|
||||
return MHD_ERR_CONNRESET_;
|
||||
/* Treat any other error as hard error. */
|
||||
return MHD_ERR_NOTCONN_;
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
return MHD_ERR_AGAIN_;
|
||||
if (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_ECONNRESET_))
|
||||
return MHD_ERR_CONNRESET_;
|
||||
/* Treat any other error as hard error. */
|
||||
return MHD_ERR_NOTCONN_;
|
||||
}
|
||||
#ifdef EPOLL_SUPPORT
|
||||
else if (i > (size_t)ret)
|
||||
else if (i > (size_t) ret)
|
||||
connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
|
||||
#endif /* EPOLL_SUPPORT */
|
||||
return ret;
|
||||
@@ -582,11 +584,11 @@ send_param_adapter (struct MHD_Connection *connection,
|
||||
*/
|
||||
static enum MHD_StatusCode
|
||||
internal_add_connection (struct MHD_Daemon *daemon,
|
||||
MHD_socket client_socket,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
bool external_add,
|
||||
bool non_blck)
|
||||
MHD_socket client_socket,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
bool external_add,
|
||||
bool non_blck)
|
||||
{
|
||||
enum MHD_StatusCode sc;
|
||||
struct MHD_Connection *connection;
|
||||
@@ -594,78 +596,78 @@ internal_add_connection (struct MHD_Daemon *daemon,
|
||||
|
||||
/* Direct add to master daemon could happen only with "external" add mode. */
|
||||
mhd_assert ( (NULL == daemon->worker_pool) ||
|
||||
(external_add) );
|
||||
(external_add) );
|
||||
if ( (external_add) &&
|
||||
(NULL != daemon->worker_pool) )
|
||||
{
|
||||
unsigned int i;
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* have a pool, try to find a pool with capacity; we use the
|
||||
socket as the initial offset into the pool for load
|
||||
balancing */
|
||||
for (i = 0; i < daemon->worker_pool_size; ++i)
|
||||
{
|
||||
struct MHD_Daemon * const worker =
|
||||
&daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
|
||||
if (worker->connections < worker->global_connection_limit)
|
||||
return internal_add_connection (worker,
|
||||
client_socket,
|
||||
addr,
|
||||
addrlen,
|
||||
true,
|
||||
non_blck);
|
||||
}
|
||||
/* all pools are at their connection limit, must refuse */
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
/* have a pool, try to find a pool with capacity; we use the
|
||||
socket as the initial offset into the pool for load
|
||||
balancing */
|
||||
for (i = 0; i < daemon->worker_pool_size; ++i)
|
||||
{
|
||||
struct MHD_Daemon *const worker =
|
||||
&daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
|
||||
if (worker->connections < worker->global_connection_limit)
|
||||
return internal_add_connection (worker,
|
||||
client_socket,
|
||||
addr,
|
||||
addrlen,
|
||||
true,
|
||||
non_blck);
|
||||
}
|
||||
/* all pools are at their connection limit, must refuse */
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
#if ENFILE
|
||||
errno = ENFILE;
|
||||
errno = ENFILE;
|
||||
#endif
|
||||
return MHD_SC_LIMIT_CONNECTIONS_REACHED;
|
||||
}
|
||||
return MHD_SC_LIMIT_CONNECTIONS_REACHED;
|
||||
}
|
||||
|
||||
if ( (! MHD_SCKT_FD_FITS_FDSET_(client_socket,
|
||||
NULL)) &&
|
||||
if ( (! MHD_SCKT_FD_FITS_FDSET_ (client_socket,
|
||||
NULL)) &&
|
||||
(MHD_ELS_SELECT == daemon->event_loop_syscall) )
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
|
||||
_("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
|
||||
(int) client_socket,
|
||||
(int) FD_SETSIZE);
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
|
||||
_ ("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
|
||||
(int) client_socket,
|
||||
(int) FD_SETSIZE);
|
||||
#endif
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
#if EINVAL
|
||||
errno = EINVAL;
|
||||
errno = EINVAL;
|
||||
#endif
|
||||
return MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
}
|
||||
return MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
}
|
||||
|
||||
#ifdef MHD_socket_nosignal_
|
||||
if (! MHD_socket_nosignal_ (client_socket))
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_CONFIGURE_NOSIGPIPE_FAILED,
|
||||
_("Failed to set SO_NOSIGPIPE on accepted socket: %s\n"),
|
||||
MHD_socket_last_strerr_());
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_CONFIGURE_NOSIGPIPE_FAILED,
|
||||
_ ("Failed to set SO_NOSIGPIPE on accepted socket: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
#ifndef MSG_NOSIGNAL
|
||||
/* Cannot use socket as it can produce SIGPIPE. */
|
||||
/* Cannot use socket as it can produce SIGPIPE. */
|
||||
#ifdef ENOTSOCK
|
||||
errno = ENOTSOCK;
|
||||
errno = ENOTSOCK;
|
||||
#endif /* ENOTSOCK */
|
||||
return MHD_SC_ACCEPT_CONFIGURE_NOSIGPIPE_FAILED;
|
||||
return MHD_SC_ACCEPT_CONFIGURE_NOSIGPIPE_FAILED;
|
||||
#endif /* ! MSG_NOSIGNAL */
|
||||
}
|
||||
}
|
||||
#endif /* MHD_socket_nosignal_ */
|
||||
|
||||
|
||||
#ifdef HAVE_MESSAGES
|
||||
#if DEBUG_CONNECT
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_CONNECTION_ACCEPTED,
|
||||
_("Accepted connection on socket %d\n"),
|
||||
MHD_SC_CONNECTION_ACCEPTED,
|
||||
_ ("Accepted connection on socket %d\n"),
|
||||
client_socket);
|
||||
#endif
|
||||
#endif
|
||||
@@ -673,82 +675,83 @@ internal_add_connection (struct MHD_Daemon *daemon,
|
||||
(MHD_NO == MHD_ip_limit_add (daemon,
|
||||
addr,
|
||||
addrlen)) )
|
||||
{
|
||||
/* above connection limit - reject */
|
||||
{
|
||||
/* above connection limit - reject */
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LIMIT_CONNECTIONS_REACHED,
|
||||
_("Server reached connection limit. Closing inbound connection.\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LIMIT_CONNECTIONS_REACHED,
|
||||
_ (
|
||||
"Server reached connection limit. Closing inbound connection.\n"));
|
||||
#endif
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
#if ENFILE
|
||||
errno = ENFILE;
|
||||
errno = ENFILE;
|
||||
#endif
|
||||
return MHD_SC_LIMIT_CONNECTIONS_REACHED;
|
||||
}
|
||||
return MHD_SC_LIMIT_CONNECTIONS_REACHED;
|
||||
}
|
||||
|
||||
/* apply connection acceptance policy if present */
|
||||
if ( (NULL != daemon->accept_policy_cb) &&
|
||||
(MHD_NO ==
|
||||
daemon->accept_policy_cb (daemon->accept_policy_cb_cls,
|
||||
addr,
|
||||
addrlen)) )
|
||||
{
|
||||
daemon->accept_policy_cb (daemon->accept_policy_cb_cls,
|
||||
addr,
|
||||
addrlen)) )
|
||||
{
|
||||
#if DEBUG_CLOSE
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_POLICY_REJECTED,
|
||||
_("Connection rejected by application. Closing connection.\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_POLICY_REJECTED,
|
||||
_ ("Connection rejected by application. Closing connection.\n"));
|
||||
#endif
|
||||
#endif
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
MHD_ip_limit_del (daemon,
|
||||
addr,
|
||||
addrlen);
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
MHD_ip_limit_del (daemon,
|
||||
addr,
|
||||
addrlen);
|
||||
#if EACCESS
|
||||
errno = EACCESS;
|
||||
errno = EACCESS;
|
||||
#endif
|
||||
return MHD_SC_ACCEPT_POLICY_REJECTED;
|
||||
}
|
||||
return MHD_SC_ACCEPT_POLICY_REJECTED;
|
||||
}
|
||||
|
||||
if (NULL ==
|
||||
(connection = MHD_calloc_ (1,
|
||||
sizeof (struct MHD_Connection))))
|
||||
{
|
||||
eno = errno;
|
||||
sizeof (struct MHD_Connection))))
|
||||
{
|
||||
eno = errno;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_CONNECTION_MALLOC_FAILURE,
|
||||
"Error allocating memory: %s\n",
|
||||
MHD_strerror_ (errno));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_CONNECTION_MALLOC_FAILURE,
|
||||
"Error allocating memory: %s\n",
|
||||
MHD_strerror_ (errno));
|
||||
#endif
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
MHD_ip_limit_del (daemon,
|
||||
addr,
|
||||
addrlen);
|
||||
errno = eno;
|
||||
return MHD_SC_CONNECTION_MALLOC_FAILURE;
|
||||
}
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
MHD_ip_limit_del (daemon,
|
||||
addr,
|
||||
addrlen);
|
||||
errno = eno;
|
||||
return MHD_SC_CONNECTION_MALLOC_FAILURE;
|
||||
}
|
||||
connection->pool
|
||||
= MHD_pool_create (daemon->connection_memory_limit_b);
|
||||
if (NULL == connection->pool)
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_POOL_MALLOC_FAILURE,
|
||||
_("Error allocating memory: %s\n"),
|
||||
MHD_strerror_ (errno));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_POOL_MALLOC_FAILURE,
|
||||
_ ("Error allocating memory: %s\n"),
|
||||
MHD_strerror_ (errno));
|
||||
#endif
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
MHD_ip_limit_del (daemon,
|
||||
addr,
|
||||
addrlen);
|
||||
free (connection);
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
MHD_ip_limit_del (daemon,
|
||||
addr,
|
||||
addrlen);
|
||||
free (connection);
|
||||
#if ENOMEM
|
||||
errno = ENOMEM;
|
||||
errno = ENOMEM;
|
||||
#endif
|
||||
return MHD_SC_POOL_MALLOC_FAILURE;
|
||||
}
|
||||
return MHD_SC_POOL_MALLOC_FAILURE;
|
||||
}
|
||||
|
||||
connection->connection_timeout = daemon->connection_default_timeout;
|
||||
memcpy (&connection->addr,
|
||||
@@ -758,148 +761,151 @@ internal_add_connection (struct MHD_Daemon *daemon,
|
||||
connection->socket_fd = client_socket;
|
||||
connection->sk_nonblck = non_blck;
|
||||
connection->daemon = daemon;
|
||||
connection->last_activity = MHD_monotonic_sec_counter();
|
||||
connection->last_activity = MHD_monotonic_sec_counter ();
|
||||
|
||||
#ifdef HTTPS_SUPPORT
|
||||
if (NULL != daemon->tls_api)
|
||||
{
|
||||
connection->tls_cs
|
||||
= daemon->tls_api->setup_connection (daemon->tls_api->cls,
|
||||
NULL /* FIXME */);
|
||||
if (NULL == connection->tls_cs)
|
||||
{
|
||||
connection->tls_cs
|
||||
= daemon->tls_api->setup_connection (daemon->tls_api->cls,
|
||||
NULL /* FIXME */);
|
||||
if (NULL == connection->tls_cs)
|
||||
{
|
||||
eno = EINVAL;
|
||||
sc = -1; // FIXME!
|
||||
goto cleanup;
|
||||
}
|
||||
eno = EINVAL;
|
||||
sc = -1; // FIXME!
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* ! HTTPS_SUPPORT */
|
||||
{
|
||||
/* set default connection handlers */
|
||||
connection->recv_cls = &recv_param_adapter;
|
||||
connection->send_cls = &send_param_adapter;
|
||||
}
|
||||
{
|
||||
/* set default connection handlers */
|
||||
connection->recv_cls = &recv_param_adapter;
|
||||
connection->send_cls = &send_param_adapter;
|
||||
}
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
/* Firm check under lock. */
|
||||
if (daemon->connections >= daemon->global_connection_limit)
|
||||
{
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
/* above connection limit - reject */
|
||||
{
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
/* above connection limit - reject */
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LIMIT_CONNECTIONS_REACHED,
|
||||
_("Server reached connection limit. Closing inbound connection.\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LIMIT_CONNECTIONS_REACHED,
|
||||
_ (
|
||||
"Server reached connection limit. Closing inbound connection.\n"));
|
||||
#endif
|
||||
#if ENFILE
|
||||
eno = ENFILE;
|
||||
eno = ENFILE;
|
||||
#endif
|
||||
sc = MHD_SC_LIMIT_CONNECTIONS_REACHED;
|
||||
goto cleanup;
|
||||
}
|
||||
sc = MHD_SC_LIMIT_CONNECTIONS_REACHED;
|
||||
goto cleanup;
|
||||
}
|
||||
daemon->connections++;
|
||||
if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
|
||||
{
|
||||
XDLL_insert (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
}
|
||||
{
|
||||
XDLL_insert (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
}
|
||||
DLL_insert (daemon->connections_head,
|
||||
daemon->connections_tail,
|
||||
connection);
|
||||
daemon->connections_tail,
|
||||
connection);
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
|
||||
if (NULL != daemon->notify_connection_cb)
|
||||
daemon->notify_connection_cb (daemon->notify_connection_cb_cls,
|
||||
connection,
|
||||
MHD_CONNECTION_NOTIFY_STARTED);
|
||||
connection,
|
||||
MHD_CONNECTION_NOTIFY_STARTED);
|
||||
|
||||
/* attempt to create handler thread */
|
||||
if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
|
||||
{
|
||||
if (! MHD_create_named_thread_ (&connection->pid,
|
||||
"MHD-connection",
|
||||
daemon->thread_stack_limit_b,
|
||||
&thread_main_handle_connection,
|
||||
connection))
|
||||
{
|
||||
if (! MHD_create_named_thread_ (&connection->pid,
|
||||
"MHD-connection",
|
||||
daemon->thread_stack_limit_b,
|
||||
&thread_main_handle_connection,
|
||||
connection))
|
||||
{
|
||||
eno = errno;
|
||||
eno = errno;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_THREAD_LAUNCH_FAILURE,
|
||||
"Failed to create a thread: %s\n",
|
||||
MHD_strerror_ (eno));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_THREAD_LAUNCH_FAILURE,
|
||||
"Failed to create a thread: %s\n",
|
||||
MHD_strerror_ (eno));
|
||||
#endif
|
||||
sc = MHD_SC_THREAD_LAUNCH_FAILURE;
|
||||
goto cleanup;
|
||||
}
|
||||
sc = MHD_SC_THREAD_LAUNCH_FAILURE;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
connection->pid = daemon->pid;
|
||||
}
|
||||
{
|
||||
connection->pid = daemon->pid;
|
||||
}
|
||||
#ifdef EPOLL_SUPPORT
|
||||
if (MHD_ELS_EPOLL == daemon->event_loop_syscall)
|
||||
{
|
||||
if ( (! daemon->enable_turbo) ||
|
||||
(external_add))
|
||||
{ /* Do not manipulate EReady DL-list in 'external_add' mode. */
|
||||
struct epoll_event event;
|
||||
{
|
||||
if ( (! daemon->enable_turbo) ||
|
||||
(external_add))
|
||||
{ /* Do not manipulate EReady DL-list in 'external_add' mode. */
|
||||
struct epoll_event event;
|
||||
|
||||
event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
|
||||
event.data.ptr = connection;
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_ADD,
|
||||
client_socket,
|
||||
&event))
|
||||
{
|
||||
eno = errno;
|
||||
event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
|
||||
event.data.ptr = connection;
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_ADD,
|
||||
client_socket,
|
||||
&event))
|
||||
{
|
||||
eno = errno;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_ADD_FAILED,
|
||||
_("Call to epoll_ctl failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_ADD_FAILED,
|
||||
_ ("Call to epoll_ctl failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
sc = MHD_SC_EPOLL_CTL_ADD_FAILED;
|
||||
goto cleanup;
|
||||
}
|
||||
connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
connection->epoll_state |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY
|
||||
| MHD_EPOLL_STATE_IN_EREADY_EDLL;
|
||||
EDLL_insert (daemon->eready_head,
|
||||
daemon->eready_tail,
|
||||
connection);
|
||||
}
|
||||
sc = MHD_SC_EPOLL_CTL_ADD_FAILED;
|
||||
goto cleanup;
|
||||
}
|
||||
connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
connection->epoll_state |= MHD_EPOLL_STATE_READ_READY
|
||||
| MHD_EPOLL_STATE_WRITE_READY
|
||||
| MHD_EPOLL_STATE_IN_EREADY_EDLL;
|
||||
EDLL_insert (daemon->eready_head,
|
||||
daemon->eready_tail,
|
||||
connection);
|
||||
}
|
||||
}
|
||||
else /* This 'else' is combined with next 'if'. */
|
||||
#endif
|
||||
if ( (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode) &&
|
||||
(external_add) &&
|
||||
(MHD_ITC_IS_VALID_(daemon->itc)) &&
|
||||
(MHD_ITC_IS_VALID_ (daemon->itc)) &&
|
||||
(! MHD_itc_activate_ (daemon->itc,
|
||||
"n")) )
|
||||
{
|
||||
"n")) )
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ITC_USE_FAILED,
|
||||
_("Failed to signal new connection via inter-thread communication channel (not necessarily fatal, continuing anyway)."));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ITC_USE_FAILED,
|
||||
_ (
|
||||
"Failed to signal new connection via inter-thread communication channel (not necessarily fatal, continuing anyway)."));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return MHD_SC_OK;
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (NULL != daemon->notify_connection_cb)
|
||||
daemon->notify_connection_cb (daemon->notify_connection_cb_cls,
|
||||
connection,
|
||||
MHD_CONNECTION_NOTIFY_CLOSED);
|
||||
connection,
|
||||
MHD_CONNECTION_NOTIFY_CLOSED);
|
||||
#ifdef HTTPS_SUPPORT
|
||||
if ( (NULL != daemon->tls_api) &&
|
||||
(NULL != connection->tls_cs) )
|
||||
daemon->tls_api->teardown_connection (daemon->tls_api->cls,
|
||||
connection->tls_cs);
|
||||
daemon->tls_api->teardown_connection (daemon->tls_api->cls,
|
||||
connection->tls_cs);
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
MHD_socket_close_chk_ (client_socket);
|
||||
MHD_ip_limit_del (daemon,
|
||||
@@ -907,14 +913,14 @@ internal_add_connection (struct MHD_Daemon *daemon,
|
||||
addrlen);
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
|
||||
{
|
||||
XDLL_remove (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
}
|
||||
{
|
||||
XDLL_remove (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
}
|
||||
DLL_remove (daemon->connections_head,
|
||||
daemon->connections_tail,
|
||||
connection);
|
||||
daemon->connections_tail,
|
||||
connection);
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
MHD_pool_destroy (connection->pool);
|
||||
free (connection);
|
||||
@@ -954,42 +960,42 @@ internal_add_connection (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_add_connection (struct MHD_Daemon *daemon,
|
||||
MHD_socket client_socket,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
MHD_socket client_socket,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
bool sk_nonbl;
|
||||
|
||||
if (! MHD_socket_nonblocking_ (client_socket))
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_CONFIGURE_NONBLOCKING_FAILED,
|
||||
_("Failed to set nonblocking mode on new client socket: %s\n"),
|
||||
MHD_socket_last_strerr_());
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_CONFIGURE_NONBLOCKING_FAILED,
|
||||
_ ("Failed to set nonblocking mode on new client socket: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
sk_nonbl = false;
|
||||
}
|
||||
sk_nonbl = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
sk_nonbl = true;
|
||||
}
|
||||
{
|
||||
sk_nonbl = true;
|
||||
}
|
||||
|
||||
if ( (daemon->enable_turbo) &&
|
||||
(! MHD_socket_noninheritable_ (client_socket)) )
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_CONFIGURE_NOINHERIT_FAILED,
|
||||
_("Failed to set noninheritable mode on new client socket.\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_CONFIGURE_NOINHERIT_FAILED,
|
||||
_ ("Failed to set noninheritable mode on new client socket.\n"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return internal_add_connection (daemon,
|
||||
client_socket,
|
||||
addr,
|
||||
client_socket,
|
||||
addr,
|
||||
addrlen,
|
||||
true,
|
||||
sk_nonbl);
|
||||
true,
|
||||
sk_nonbl);
|
||||
}
|
||||
|
||||
|
||||
@@ -1033,94 +1039,98 @@ MHD_accept_connection_ (struct MHD_Daemon *daemon)
|
||||
#endif /* ! USE_ACCEPT4 */
|
||||
if ( (MHD_INVALID_SOCKET == s) ||
|
||||
(addrlen <= 0) )
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
|
||||
/* This could be a common occurance with multiple worker threads */
|
||||
if (MHD_SCKT_ERR_IS_ (err,
|
||||
MHD_SCKT_EINVAL_))
|
||||
return MHD_SC_DAEMON_ALREADY_SHUTDOWN; /* can happen during shutdown, let's hope this is the cause... */
|
||||
if (MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err))
|
||||
return MHD_SC_ACCEPT_FAST_DISCONNECT; /* do not print error if client just disconnected early */
|
||||
if (MHD_SCKT_ERR_IS_EAGAIN_ (err) )
|
||||
return MHD_SC_ACCEPT_FAILED_EAGAIN;
|
||||
if (MHD_INVALID_SOCKET != s)
|
||||
{
|
||||
MHD_socket_close_chk_ (s);
|
||||
}
|
||||
if ( MHD_SCKT_ERR_IS_LOW_RESOURCES_ (err) )
|
||||
{
|
||||
/* system/process out of resources */
|
||||
if (0 == daemon->connections)
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
/* Not setting 'at_limit' flag, as there is no way it
|
||||
would ever be cleared. Instead trying to produce
|
||||
bit fat ugly warning. */
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED_INSTANTLY,
|
||||
_("Hit process or system resource limit at FIRST connection. This is really bad as there is no sane way to proceed. Will try busy waiting for system resources to become magically available.\n"));
|
||||
#endif
|
||||
return MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED_INSTANTLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
daemon->at_limit = true;
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED,
|
||||
_("Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
|
||||
(unsigned int) daemon->connections);
|
||||
#endif
|
||||
return MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED;
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_FAILED_UNEXPECTEDLY,
|
||||
_("Error accepting connection: %s\n"),
|
||||
MHD_socket_strerr_(err));
|
||||
#endif
|
||||
return MHD_SC_ACCEPT_FAILED_UNEXPECTEDLY;
|
||||
}
|
||||
#if !defined(USE_ACCEPT4) || !defined(HAVE_SOCK_NONBLOCK)
|
||||
if (! MHD_socket_nonblocking_ (s))
|
||||
/* This could be a common occurance with multiple worker threads */
|
||||
if (MHD_SCKT_ERR_IS_ (err,
|
||||
MHD_SCKT_EINVAL_))
|
||||
return MHD_SC_DAEMON_ALREADY_SHUTDOWN; /* can happen during shutdown, let's hope this is the cause... */
|
||||
if (MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_ (err))
|
||||
return MHD_SC_ACCEPT_FAST_DISCONNECT; /* do not print error if client just disconnected early */
|
||||
if (MHD_SCKT_ERR_IS_EAGAIN_ (err) )
|
||||
return MHD_SC_ACCEPT_FAILED_EAGAIN;
|
||||
if (MHD_INVALID_SOCKET != s)
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_CONFIGURE_NONBLOCKING_FAILED,
|
||||
_("Failed to set nonblocking mode on incoming connection socket: %s\n"),
|
||||
MHD_socket_last_strerr_());
|
||||
#endif
|
||||
MHD_socket_close_chk_ (s);
|
||||
}
|
||||
if ( MHD_SCKT_ERR_IS_LOW_RESOURCES_ (err) )
|
||||
{
|
||||
/* system/process out of resources */
|
||||
if (0 == daemon->connections)
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
/* Not setting 'at_limit' flag, as there is no way it
|
||||
would ever be cleared. Instead trying to produce
|
||||
bit fat ugly warning. */
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED_INSTANTLY,
|
||||
_ (
|
||||
"Hit process or system resource limit at FIRST connection. This is really bad as there is no sane way to proceed. Will try busy waiting for system resources to become magically available.\n"));
|
||||
#endif
|
||||
return MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED_INSTANTLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
daemon->at_limit = true;
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED,
|
||||
_ (
|
||||
"Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
|
||||
(unsigned int) daemon->connections);
|
||||
#endif
|
||||
return MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED;
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_FAILED_UNEXPECTEDLY,
|
||||
_ ("Error accepting connection: %s\n"),
|
||||
MHD_socket_strerr_ (err));
|
||||
#endif
|
||||
return MHD_SC_ACCEPT_FAILED_UNEXPECTEDLY;
|
||||
}
|
||||
#if ! defined(USE_ACCEPT4) || ! defined(HAVE_SOCK_NONBLOCK)
|
||||
if (! MHD_socket_nonblocking_ (s))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_CONFIGURE_NONBLOCKING_FAILED,
|
||||
_ (
|
||||
"Failed to set nonblocking mode on incoming connection socket: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
}
|
||||
else
|
||||
sk_nonbl = true;
|
||||
#endif /* !USE_ACCEPT4 || !HAVE_SOCK_NONBLOCK */
|
||||
#if !defined(USE_ACCEPT4) || !defined(SOCK_CLOEXEC)
|
||||
#if ! defined(USE_ACCEPT4) || ! defined(SOCK_CLOEXEC)
|
||||
if (! MHD_socket_noninheritable_ (s))
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_CONFIGURE_NOINHERIT_FAILED,
|
||||
_("Failed to set noninheritable mode on incoming connection socket.\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ACCEPT_CONFIGURE_NOINHERIT_FAILED,
|
||||
_ (
|
||||
"Failed to set noninheritable mode on incoming connection socket.\n"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif /* !USE_ACCEPT4 || !SOCK_CLOEXEC */
|
||||
#ifdef HAVE_MESSAGES
|
||||
#if DEBUG_CONNECT
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_CONNECTION_ACCEPTED,
|
||||
_("Accepted connection on socket %d\n"),
|
||||
MHD_SC_CONNECTION_ACCEPTED,
|
||||
_ ("Accepted connection on socket %d\n"),
|
||||
s);
|
||||
#endif
|
||||
#endif
|
||||
return internal_add_connection (daemon,
|
||||
s,
|
||||
addr,
|
||||
addr,
|
||||
addrlen,
|
||||
false,
|
||||
false,
|
||||
sk_nonbl);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,10 +32,10 @@
|
||||
* that process daemon's select()/poll()/etc.
|
||||
*
|
||||
* @param daemon handle with the listen socket
|
||||
* @return #MHD_SC_OK on success
|
||||
* @return #MHD_SC_OK on success
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_accept_connection_ (struct MHD_Daemon *daemon)
|
||||
MHD_NONNULL (1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
#endif
|
||||
|
||||
+2077
-2045
@@ -56,7 +56,8 @@
|
||||
* minimal.
|
||||
*/
|
||||
#ifdef HAVE_MESSAGES
|
||||
#define REQUEST_TOO_BIG "<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>"
|
||||
#define REQUEST_TOO_BIG \
|
||||
"<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>"
|
||||
#else
|
||||
#define REQUEST_TOO_BIG ""
|
||||
#endif
|
||||
@@ -69,7 +70,8 @@
|
||||
* minimal.
|
||||
*/
|
||||
#ifdef HAVE_MESSAGES
|
||||
#define REQUEST_LACKS_HOST "<html><head><title>"Host:" header required</title></head><body>In HTTP 1.1, requests must include a "Host:" header, and your HTTP 1.1 request lacked such a header.</body></html>"
|
||||
#define REQUEST_LACKS_HOST \
|
||||
"<html><head><title>"Host:" header required</title></head><body>In HTTP 1.1, requests must include a "Host:" header, and your HTTP 1.1 request lacked such a header.</body></html>"
|
||||
#else
|
||||
#define REQUEST_LACKS_HOST ""
|
||||
#endif
|
||||
@@ -82,7 +84,8 @@
|
||||
* minimal.
|
||||
*/
|
||||
#ifdef HAVE_MESSAGES
|
||||
#define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
|
||||
#define REQUEST_MALFORMED \
|
||||
"<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
|
||||
#else
|
||||
#define REQUEST_MALFORMED ""
|
||||
#endif
|
||||
@@ -94,7 +97,8 @@
|
||||
* minimal.
|
||||
*/
|
||||
#ifdef HAVE_MESSAGES
|
||||
#define INTERNAL_ERROR "<html><head><title>Internal server error</title></head><body>Please ask the developer of this Web server to carefully read the GNU libmicrohttpd documentation about connection management and blocking.</body></html>"
|
||||
#define INTERNAL_ERROR \
|
||||
"<html><head><title>Internal server error</title></head><body>Please ask the developer of this Web server to carefully read the GNU libmicrohttpd documentation about connection management and blocking.</body></html>"
|
||||
#else
|
||||
#define INTERNAL_ERROR ""
|
||||
#endif
|
||||
@@ -128,17 +132,18 @@ MHD_conn_init_static_ (void)
|
||||
#ifdef SF_FLAGS
|
||||
long sys_page_size = sysconf (_SC_PAGESIZE);
|
||||
if (0 > sys_page_size)
|
||||
{ /* Failed to get page size. */
|
||||
freebsd_sendfile_flags_ = SF_NODISKIO;
|
||||
freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO;
|
||||
}
|
||||
{ /* Failed to get page size. */
|
||||
freebsd_sendfile_flags_ = SF_NODISKIO;
|
||||
freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO;
|
||||
}
|
||||
else
|
||||
{
|
||||
freebsd_sendfile_flags_ =
|
||||
SF_FLAGS((uint16_t)(MHD_SENFILE_CHUNK_ / sys_page_size), SF_NODISKIO);
|
||||
freebsd_sendfile_flags_thd_p_c_ =
|
||||
SF_FLAGS((uint16_t)(MHD_SENFILE_CHUNK_THR_P_C_ / sys_page_size), SF_NODISKIO);
|
||||
}
|
||||
{
|
||||
freebsd_sendfile_flags_ =
|
||||
SF_FLAGS ((uint16_t) (MHD_SENFILE_CHUNK_ / sys_page_size), SF_NODISKIO);
|
||||
freebsd_sendfile_flags_thd_p_c_ =
|
||||
SF_FLAGS ((uint16_t) (MHD_SENFILE_CHUNK_THR_P_C_ / sys_page_size),
|
||||
SF_NODISKIO);
|
||||
}
|
||||
#endif /* SF_FLAGS */
|
||||
}
|
||||
#endif /* HAVE_FREEBSD_SENDFILE */
|
||||
@@ -161,13 +166,13 @@ MHD_conn_init_static_ (void)
|
||||
*/
|
||||
static void
|
||||
connection_close_error (struct MHD_Connection *connection,
|
||||
enum MHD_StatusCode sc,
|
||||
const char *emsg)
|
||||
enum MHD_StatusCode sc,
|
||||
const char *emsg)
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
if (NULL != emsg)
|
||||
MHD_DLOG (connection->daemon,
|
||||
sc,
|
||||
sc,
|
||||
emsg);
|
||||
#else /* ! HAVE_MESSAGES */
|
||||
(void) emsg; /* Mute compiler warning. */
|
||||
@@ -209,8 +214,8 @@ try_grow_read_buffer (struct MHD_Request *request)
|
||||
if (0 == request->read_buffer_size)
|
||||
new_size = daemon->connection_memory_limit_b / 2;
|
||||
else
|
||||
new_size = request->read_buffer_size +
|
||||
daemon->connection_memory_increment_b;
|
||||
new_size = request->read_buffer_size
|
||||
+ daemon->connection_memory_increment_b;
|
||||
buf = MHD_pool_reallocate (request->connection->pool,
|
||||
request->read_buffer,
|
||||
request->read_buffer_size,
|
||||
@@ -245,16 +250,16 @@ MHD_request_handle_read_ (struct MHD_Request *request)
|
||||
struct MHD_TLS_Plugin *tls;
|
||||
|
||||
if ( (NULL != (tls = daemon->tls_api)) &&
|
||||
(! tls->handshake (tls->cls,
|
||||
connection->tls_cs)) )
|
||||
(! tls->handshake (tls->cls,
|
||||
connection->tls_cs)) )
|
||||
return;
|
||||
}
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
|
||||
/* make sure "read" has a reasonable number of bytes
|
||||
in buffer to use per system call (if possible) */
|
||||
if (request->read_buffer_offset +
|
||||
daemon->connection_memory_increment_b >
|
||||
if (request->read_buffer_offset
|
||||
+ daemon->connection_memory_increment_b >
|
||||
request->read_buffer_size)
|
||||
try_grow_read_buffer (request);
|
||||
|
||||
@@ -263,82 +268,84 @@ MHD_request_handle_read_ (struct MHD_Request *request)
|
||||
bytes_read = connection->recv_cls (connection,
|
||||
&request->read_buffer
|
||||
[request->read_buffer_offset],
|
||||
request->read_buffer_size -
|
||||
request->read_buffer_offset);
|
||||
request->read_buffer_size
|
||||
- request->read_buffer_offset);
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
if (MHD_ERR_AGAIN_ == bytes_read)
|
||||
return; /* No new data to process. */
|
||||
if (MHD_ERR_CONNRESET_ == bytes_read)
|
||||
{
|
||||
if (MHD_ERR_AGAIN_ == bytes_read)
|
||||
return; /* No new data to process. */
|
||||
if (MHD_ERR_CONNRESET_ == bytes_read)
|
||||
{
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
(MHD_REQUEST_INIT == request->state)
|
||||
? MHD_SC_CONNECTION_CLOSED
|
||||
: MHD_SC_CONNECTION_RESET_CLOSED,
|
||||
(MHD_REQUEST_INIT == request->state)
|
||||
? NULL
|
||||
: _("Socket disconnected while reading request.\n"));
|
||||
return;
|
||||
}
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
(MHD_REQUEST_INIT == request->state)
|
||||
? MHD_SC_CONNECTION_CLOSED
|
||||
: MHD_SC_CONNECTION_READ_FAIL_CLOSED,
|
||||
(MHD_REQUEST_INIT == request->state)
|
||||
? NULL
|
||||
: _("Connection socket is closed due to error when reading request.\n"));
|
||||
? MHD_SC_CONNECTION_CLOSED
|
||||
: MHD_SC_CONNECTION_RESET_CLOSED,
|
||||
(MHD_REQUEST_INIT == request->state)
|
||||
? NULL
|
||||
: _ (
|
||||
"Socket disconnected while reading request.\n"));
|
||||
return;
|
||||
}
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
(MHD_REQUEST_INIT == request->state)
|
||||
? MHD_SC_CONNECTION_CLOSED
|
||||
: MHD_SC_CONNECTION_READ_FAIL_CLOSED,
|
||||
(MHD_REQUEST_INIT == request->state)
|
||||
? NULL
|
||||
: _ (
|
||||
"Connection socket is closed due to error when reading request.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == bytes_read)
|
||||
{ /* Remote side closed connection. */
|
||||
connection->read_closed = true;
|
||||
MHD_connection_close_ (connection,
|
||||
MHD_REQUEST_TERMINATED_CLIENT_ABORT);
|
||||
return;
|
||||
}
|
||||
{ /* Remote side closed connection. */
|
||||
connection->read_closed = true;
|
||||
MHD_connection_close_ (connection,
|
||||
MHD_REQUEST_TERMINATED_CLIENT_ABORT);
|
||||
return;
|
||||
}
|
||||
request->read_buffer_offset += bytes_read;
|
||||
MHD_connection_update_last_activity_ (connection);
|
||||
#if DEBUG_STATES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_STATE_MACHINE_STATUS_REPORT,
|
||||
_("In function %s handling connection at state: %s\n"),
|
||||
MHD_SC_STATE_MACHINE_STATUS_REPORT,
|
||||
_ ("In function %s handling connection at state: %s\n"),
|
||||
__FUNCTION__,
|
||||
MHD_state_to_string (request->state));
|
||||
#endif
|
||||
switch (request->state)
|
||||
{
|
||||
case MHD_REQUEST_INIT:
|
||||
case MHD_REQUEST_URL_RECEIVED:
|
||||
case MHD_REQUEST_HEADER_PART_RECEIVED:
|
||||
case MHD_REQUEST_HEADERS_RECEIVED:
|
||||
case MHD_REQUEST_HEADERS_PROCESSED:
|
||||
case MHD_REQUEST_CONTINUE_SENDING:
|
||||
case MHD_REQUEST_CONTINUE_SENT:
|
||||
case MHD_REQUEST_BODY_RECEIVED:
|
||||
case MHD_REQUEST_FOOTER_PART_RECEIVED:
|
||||
/* nothing to do but default action */
|
||||
if (connection->read_closed)
|
||||
{
|
||||
case MHD_REQUEST_INIT:
|
||||
case MHD_REQUEST_URL_RECEIVED:
|
||||
case MHD_REQUEST_HEADER_PART_RECEIVED:
|
||||
case MHD_REQUEST_HEADERS_RECEIVED:
|
||||
case MHD_REQUEST_HEADERS_PROCESSED:
|
||||
case MHD_REQUEST_CONTINUE_SENDING:
|
||||
case MHD_REQUEST_CONTINUE_SENT:
|
||||
case MHD_REQUEST_BODY_RECEIVED:
|
||||
case MHD_REQUEST_FOOTER_PART_RECEIVED:
|
||||
/* nothing to do but default action */
|
||||
if (connection->read_closed)
|
||||
{
|
||||
MHD_connection_close_ (connection,
|
||||
MHD_REQUEST_TERMINATED_READ_ERROR);
|
||||
}
|
||||
return;
|
||||
case MHD_REQUEST_CLOSED:
|
||||
return;
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
case MHD_REQUEST_UPGRADE:
|
||||
mhd_assert (0);
|
||||
return;
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
default:
|
||||
/* shrink read buffer to how much is actually used */
|
||||
MHD_pool_reallocate (connection->pool,
|
||||
request->read_buffer,
|
||||
request->read_buffer_size + 1,
|
||||
request->read_buffer_offset);
|
||||
break;
|
||||
MHD_connection_close_ (connection,
|
||||
MHD_REQUEST_TERMINATED_READ_ERROR);
|
||||
}
|
||||
return;
|
||||
case MHD_REQUEST_CLOSED:
|
||||
return;
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
case MHD_REQUEST_UPGRADE:
|
||||
mhd_assert (0);
|
||||
return;
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
default:
|
||||
/* shrink read buffer to how much is actually used */
|
||||
MHD_pool_reallocate (connection->pool,
|
||||
request->read_buffer,
|
||||
request->read_buffer_size + 1,
|
||||
request->read_buffer_offset);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -361,9 +368,9 @@ sendfile_adapter (struct MHD_Connection *connection)
|
||||
uint64_t left;
|
||||
uint64_t offsetu64;
|
||||
#ifndef HAVE_SENDFILE64
|
||||
const uint64_t max_off_t = (uint64_t)OFF_T_MAX;
|
||||
const uint64_t max_off_t = (uint64_t) OFF_T_MAX;
|
||||
#else /* HAVE_SENDFILE64 */
|
||||
const uint64_t max_off_t = (uint64_t)OFF64_T_MAX;
|
||||
const uint64_t max_off_t = (uint64_t) OFF64_T_MAX;
|
||||
#endif /* HAVE_SENDFILE64 */
|
||||
#ifdef MHD_LINUX_SOLARIS_SENDFILE
|
||||
#ifndef HAVE_SENDFILE64
|
||||
@@ -379,8 +386,10 @@ sendfile_adapter (struct MHD_Connection *connection)
|
||||
#ifdef HAVE_DARWIN_SENDFILE
|
||||
off_t len;
|
||||
#endif /* HAVE_DARWIN_SENDFILE */
|
||||
const bool used_thr_p_c = (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode);
|
||||
const size_t chunk_size = used_thr_p_c ? MHD_SENFILE_CHUNK_THR_P_C_ : MHD_SENFILE_CHUNK_;
|
||||
const bool used_thr_p_c = (MHD_TM_THREAD_PER_CONNECTION ==
|
||||
daemon->threading_mode);
|
||||
const size_t chunk_size = used_thr_p_c ? MHD_SENFILE_CHUNK_THR_P_C_ :
|
||||
MHD_SENFILE_CHUNK_;
|
||||
size_t send_size = 0;
|
||||
|
||||
mhd_assert (MHD_resp_sender_sendfile == request->resp_sender);
|
||||
@@ -390,10 +399,10 @@ sendfile_adapter (struct MHD_Connection *connection)
|
||||
* use 128KiB chunks (2MiB for thread-per-connection). */
|
||||
send_size = (left > chunk_size) ? chunk_size : (size_t) left;
|
||||
if (max_off_t < offsetu64)
|
||||
{ /* Retry to send with standard 'send()'. */
|
||||
request->resp_sender = MHD_resp_sender_std;
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
{ /* Retry to send with standard 'send()'. */
|
||||
request->resp_sender = MHD_resp_sender_std;
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
#ifdef MHD_LINUX_SOLARIS_SENDFILE
|
||||
#ifndef HAVE_SENDFILE64
|
||||
offset = (off_t) offsetu64;
|
||||
@@ -409,54 +418,54 @@ sendfile_adapter (struct MHD_Connection *connection)
|
||||
send_size);
|
||||
#endif /* HAVE_SENDFILE64 */
|
||||
if (0 > ret)
|
||||
{
|
||||
const int err = MHD_socket_get_error_();
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
|
||||
if (MHD_SCKT_ERR_IS_EAGAIN_(err))
|
||||
{
|
||||
if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
|
||||
{
|
||||
#ifdef EPOLL_SUPPORT
|
||||
/* EAGAIN --- no longer write-ready */
|
||||
connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
|
||||
/* EAGAIN --- no longer write-ready */
|
||||
connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
|
||||
#endif /* EPOLL_SUPPORT */
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
return MHD_ERR_AGAIN_;
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
return MHD_ERR_AGAIN_;
|
||||
#ifdef HAVE_LINUX_SENDFILE
|
||||
if (MHD_SCKT_ERR_IS_(err,
|
||||
MHD_SCKT_EBADF_))
|
||||
return MHD_ERR_BADF_;
|
||||
/* sendfile() failed with EINVAL if mmap()-like operations are not
|
||||
supported for FD or other 'unusual' errors occurred, so we should try
|
||||
to fall back to 'SEND'; see also this thread for info on
|
||||
odd libc/Linux behavior with sendfile:
|
||||
http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */
|
||||
if (MHD_SCKT_ERR_IS_ (err,
|
||||
MHD_SCKT_EBADF_))
|
||||
return MHD_ERR_BADF_;
|
||||
/* sendfile() failed with EINVAL if mmap()-like operations are not
|
||||
supported for FD or other 'unusual' errors occurred, so we should try
|
||||
to fall back to 'SEND'; see also this thread for info on
|
||||
odd libc/Linux behavior with sendfile:
|
||||
http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */
|
||||
request->resp_sender = MHD_resp_sender_std;
|
||||
return MHD_ERR_AGAIN_;
|
||||
#else /* HAVE_SOLARIS_SENDFILE */
|
||||
if ( (EAFNOSUPPORT == err) ||
|
||||
(EINVAL == err) ||
|
||||
(EOPNOTSUPP == err) )
|
||||
{ /* Retry with standard file reader. */
|
||||
request->resp_sender = MHD_resp_sender_std;
|
||||
return MHD_ERR_AGAIN_;
|
||||
#else /* HAVE_SOLARIS_SENDFILE */
|
||||
if ( (EAFNOSUPPORT == err) ||
|
||||
(EINVAL == err) ||
|
||||
(EOPNOTSUPP == err) )
|
||||
{ /* Retry with standard file reader. */
|
||||
request->resp_sender = MHD_resp_sender_std;
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
if ( (ENOTCONN == err) ||
|
||||
(EPIPE == err) )
|
||||
{
|
||||
return MHD_ERR_CONNRESET_;
|
||||
}
|
||||
return MHD_ERR_BADF_; /* Fail hard */
|
||||
#endif /* HAVE_SOLARIS_SENDFILE */
|
||||
}
|
||||
if ( (ENOTCONN == err) ||
|
||||
(EPIPE == err) )
|
||||
{
|
||||
return MHD_ERR_CONNRESET_;
|
||||
}
|
||||
return MHD_ERR_BADF_; /* Fail hard */
|
||||
#endif /* HAVE_SOLARIS_SENDFILE */
|
||||
}
|
||||
#ifdef EPOLL_SUPPORT
|
||||
else if (send_size > (size_t)ret)
|
||||
connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
|
||||
else if (send_size > (size_t) ret)
|
||||
connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
|
||||
#endif /* EPOLL_SUPPORT */
|
||||
#elif defined(HAVE_FREEBSD_SENDFILE)
|
||||
#ifdef SF_FLAGS
|
||||
flags = used_thr_p_c ?
|
||||
freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_;
|
||||
freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_;
|
||||
#endif /* SF_FLAGS */
|
||||
if (0 != sendfile (file_fd,
|
||||
connection->socket_fd,
|
||||
@@ -465,26 +474,26 @@ sendfile_adapter (struct MHD_Connection *connection)
|
||||
NULL,
|
||||
&sent_bytes,
|
||||
flags))
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
if (MHD_SCKT_ERR_IS_EAGAIN_ (err) ||
|
||||
MHD_SCKT_ERR_IS_EINTR_ (err) ||
|
||||
(EBUSY == err) )
|
||||
{
|
||||
const int err = MHD_socket_get_error_();
|
||||
if (MHD_SCKT_ERR_IS_EAGAIN_(err) ||
|
||||
MHD_SCKT_ERR_IS_EINTR_(err) ||
|
||||
EBUSY == err)
|
||||
{
|
||||
mhd_assert (SSIZE_MAX >= sent_bytes);
|
||||
if (0 != sent_bytes)
|
||||
return (ssize_t)sent_bytes;
|
||||
mhd_assert (SSIZE_MAX >= sent_bytes);
|
||||
if (0 != sent_bytes)
|
||||
return (ssize_t) sent_bytes;
|
||||
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
/* Some unrecoverable error. Possibly file FD is not suitable
|
||||
* for sendfile(). Retry with standard send(). */
|
||||
request->resp_sender = MHD_resp_sender_std;
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
/* Some unrecoverable error. Possibly file FD is not suitable
|
||||
* for sendfile(). Retry with standard send(). */
|
||||
request->resp_sender = MHD_resp_sender_std;
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
mhd_assert (0 < sent_bytes);
|
||||
mhd_assert (SSIZE_MAX >= sent_bytes);
|
||||
ret = (ssize_t)sent_bytes;
|
||||
ret = (ssize_t) sent_bytes;
|
||||
#elif defined(HAVE_DARWIN_SENDFILE)
|
||||
len = (off_t) send_size; /* chunk always fit */
|
||||
if (0 != sendfile (file_fd,
|
||||
@@ -493,35 +502,35 @@ sendfile_adapter (struct MHD_Connection *connection)
|
||||
&len,
|
||||
NULL,
|
||||
0))
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
if (MHD_SCKT_ERR_IS_EAGAIN_ (err) ||
|
||||
MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
{
|
||||
const int err = MHD_socket_get_error_();
|
||||
if (MHD_SCKT_ERR_IS_EAGAIN_(err) ||
|
||||
MHD_SCKT_ERR_IS_EINTR_(err))
|
||||
{
|
||||
mhd_assert (0 <= len);
|
||||
mhd_assert (SSIZE_MAX >= len);
|
||||
mhd_assert (send_size >= (size_t)len);
|
||||
if (0 != len)
|
||||
return (ssize_t)len;
|
||||
mhd_assert (0 <= len);
|
||||
mhd_assert (SSIZE_MAX >= len);
|
||||
mhd_assert (send_size >= (size_t) len);
|
||||
if (0 != len)
|
||||
return (ssize_t) len;
|
||||
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
if (ENOTCONN == err ||
|
||||
EPIPE == err)
|
||||
return MHD_ERR_CONNRESET_;
|
||||
if (ENOTSUP == err ||
|
||||
EOPNOTSUPP == err)
|
||||
{ /* This file FD is not suitable for sendfile().
|
||||
* Retry with standard send(). */
|
||||
request->resp_sender = MHD_resp_sender_std;
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
return MHD_ERR_BADF_; /* Return hard error. */
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
if ((ENOTCONN == err) ||
|
||||
(EPIPE == err) )
|
||||
return MHD_ERR_CONNRESET_;
|
||||
if ((ENOTSUP == err) ||
|
||||
(EOPNOTSUPP == err) )
|
||||
{ /* This file FD is not suitable for sendfile().
|
||||
* Retry with standard send(). */
|
||||
request->resp_sender = MHD_resp_sender_std;
|
||||
return MHD_ERR_AGAIN_;
|
||||
}
|
||||
return MHD_ERR_BADF_; /* Return hard error. */
|
||||
}
|
||||
mhd_assert (0 <= len);
|
||||
mhd_assert (SSIZE_MAX >= len);
|
||||
mhd_assert (send_size >= (size_t)len);
|
||||
ret = (ssize_t)len;
|
||||
mhd_assert (send_size >= (size_t) len);
|
||||
ret = (ssize_t) len;
|
||||
#endif /* HAVE_FREEBSD_SENDFILE */
|
||||
return ret;
|
||||
}
|
||||
@@ -547,7 +556,7 @@ check_write_done (struct MHD_Request *request,
|
||||
request->write_buffer_send_offset = 0;
|
||||
request->state = next_state;
|
||||
MHD_pool_reallocate (request->connection->pool,
|
||||
request->write_buffer,
|
||||
request->write_buffer,
|
||||
request->write_buffer_size,
|
||||
0);
|
||||
request->write_buffer = NULL;
|
||||
@@ -579,47 +588,48 @@ try_ready_normal_body (struct MHD_Request *request)
|
||||
(request->response_write_position == response->total_size) )
|
||||
return true; /* 0-byte response is always ready */
|
||||
if ( (response->data_start <=
|
||||
request->response_write_position) &&
|
||||
request->response_write_position) &&
|
||||
(response->data_size + response->data_start >
|
||||
request->response_write_position) )
|
||||
request->response_write_position) )
|
||||
return true; /* response already ready */
|
||||
#if defined(_MHD_HAVE_SENDFILE)
|
||||
if (MHD_resp_sender_sendfile == request->resp_sender)
|
||||
{
|
||||
/* will use sendfile, no need to bother response crc */
|
||||
return true;
|
||||
}
|
||||
{
|
||||
/* will use sendfile, no need to bother response crc */
|
||||
return true;
|
||||
}
|
||||
#endif /* _MHD_HAVE_SENDFILE */
|
||||
|
||||
ret = response->crc (response->crc_cls,
|
||||
request->response_write_position,
|
||||
response->data,
|
||||
(size_t) MHD_MIN ((uint64_t) response->data_buffer_size,
|
||||
response->total_size -
|
||||
request->response_write_position));
|
||||
response->total_size
|
||||
- request->response_write_position));
|
||||
if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
|
||||
(((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
|
||||
{
|
||||
/* either error or http 1.0 transfer, close socket! */
|
||||
response->total_size = request->response_write_position;
|
||||
MHD_mutex_unlock_chk_ (&response->mutex);
|
||||
if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret)
|
||||
MHD_connection_close_ (connection,
|
||||
MHD_REQUEST_TERMINATED_COMPLETED_OK);
|
||||
else
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED,
|
||||
_("Closing connection (application reported error generating data)\n"));
|
||||
return false;
|
||||
}
|
||||
{
|
||||
/* either error or http 1.0 transfer, close socket! */
|
||||
response->total_size = request->response_write_position;
|
||||
MHD_mutex_unlock_chk_ (&response->mutex);
|
||||
if ( ((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret)
|
||||
MHD_connection_close_ (connection,
|
||||
MHD_REQUEST_TERMINATED_COMPLETED_OK);
|
||||
else
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED,
|
||||
_ (
|
||||
"Closing connection (application reported error generating data)\n"));
|
||||
return false;
|
||||
}
|
||||
response->data_start = request->response_write_position;
|
||||
response->data_size = ret;
|
||||
if (0 == ret)
|
||||
{
|
||||
request->state = MHD_REQUEST_NORMAL_BODY_UNREADY;
|
||||
MHD_mutex_unlock_chk_ (&response->mutex);
|
||||
return false;
|
||||
}
|
||||
{
|
||||
request->state = MHD_REQUEST_NORMAL_BODY_UNREADY;
|
||||
MHD_mutex_unlock_chk_ (&response->mutex);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -647,93 +657,94 @@ try_ready_chunked_body (struct MHD_Request *request)
|
||||
if (NULL == response->crc)
|
||||
return true;
|
||||
if (0 == request->write_buffer_size)
|
||||
{
|
||||
size = MHD_MIN (daemon->connection_memory_limit_b,
|
||||
2 * (0xFFFFFF + sizeof(cbuf) + 2));
|
||||
do
|
||||
{
|
||||
size = MHD_MIN (daemon->connection_memory_limit_b,
|
||||
2 * (0xFFFFFF + sizeof(cbuf) + 2));
|
||||
do
|
||||
{
|
||||
size /= 2;
|
||||
if (size < 128)
|
||||
{
|
||||
MHD_mutex_unlock_chk_ (&response->mutex);
|
||||
/* not enough memory */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
|
||||
_("Closing connection (out of memory)\n"));
|
||||
return false;
|
||||
}
|
||||
buf = MHD_pool_allocate (connection->pool,
|
||||
size,
|
||||
MHD_NO);
|
||||
}
|
||||
while (NULL == buf);
|
||||
request->write_buffer_size = size;
|
||||
request->write_buffer = buf;
|
||||
size /= 2;
|
||||
if (size < 128)
|
||||
{
|
||||
MHD_mutex_unlock_chk_ (&response->mutex);
|
||||
/* not enough memory */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
|
||||
_ ("Closing connection (out of memory)\n"));
|
||||
return false;
|
||||
}
|
||||
buf = MHD_pool_allocate (connection->pool,
|
||||
size,
|
||||
MHD_NO);
|
||||
}
|
||||
while (NULL == buf);
|
||||
request->write_buffer_size = size;
|
||||
request->write_buffer = buf;
|
||||
}
|
||||
|
||||
if (0 == response->total_size)
|
||||
ret = 0; /* response must be empty, don't bother calling crc */
|
||||
else if ( (response->data_start <=
|
||||
request->response_write_position) &&
|
||||
(response->data_start + response->data_size >
|
||||
request->response_write_position) )
|
||||
{
|
||||
/* difference between response_write_position and data_start is less
|
||||
than data_size which is size_t type, no need to check for overflow */
|
||||
const size_t data_write_offset
|
||||
= (size_t)(request->response_write_position - response->data_start);
|
||||
/* buffer already ready, use what is there for the chunk */
|
||||
ret = response->data_size - data_write_offset;
|
||||
if ( ((size_t) ret) > request->write_buffer_size - sizeof (cbuf) - 2 )
|
||||
ret = request->write_buffer_size - sizeof (cbuf) - 2;
|
||||
memcpy (&request->write_buffer[sizeof (cbuf)],
|
||||
&response->data[data_write_offset],
|
||||
ret);
|
||||
}
|
||||
request->response_write_position) &&
|
||||
(response->data_start + response->data_size >
|
||||
request->response_write_position) )
|
||||
{
|
||||
/* difference between response_write_position and data_start is less
|
||||
than data_size which is size_t type, no need to check for overflow */
|
||||
const size_t data_write_offset
|
||||
= (size_t) (request->response_write_position - response->data_start);
|
||||
/* buffer already ready, use what is there for the chunk */
|
||||
ret = response->data_size - data_write_offset;
|
||||
if ( ((size_t) ret) > request->write_buffer_size - sizeof (cbuf) - 2 )
|
||||
ret = request->write_buffer_size - sizeof (cbuf) - 2;
|
||||
memcpy (&request->write_buffer[sizeof (cbuf)],
|
||||
&response->data[data_write_offset],
|
||||
ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* buffer not in range, try to fill it */
|
||||
ret = response->crc (response->crc_cls,
|
||||
request->response_write_position,
|
||||
&request->write_buffer[sizeof (cbuf)],
|
||||
request->write_buffer_size - sizeof (cbuf) - 2);
|
||||
}
|
||||
{
|
||||
/* buffer not in range, try to fill it */
|
||||
ret = response->crc (response->crc_cls,
|
||||
request->response_write_position,
|
||||
&request->write_buffer[sizeof (cbuf)],
|
||||
request->write_buffer_size - sizeof (cbuf) - 2);
|
||||
}
|
||||
if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
|
||||
{
|
||||
/* error, close socket! */
|
||||
response->total_size = request->response_write_position;
|
||||
MHD_mutex_unlock_chk_ (&response->mutex);
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED,
|
||||
_("Closing connection (application error generating response)\n"));
|
||||
return false;
|
||||
}
|
||||
{
|
||||
/* error, close socket! */
|
||||
response->total_size = request->response_write_position;
|
||||
MHD_mutex_unlock_chk_ (&response->mutex);
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED,
|
||||
_ (
|
||||
"Closing connection (application error generating response)\n"));
|
||||
return false;
|
||||
}
|
||||
if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
|
||||
(0 == response->total_size) )
|
||||
{
|
||||
/* end of message, signal other side! */
|
||||
memcpy (request->write_buffer,
|
||||
"0\r\n",
|
||||
3);
|
||||
request->write_buffer_append_offset = 3;
|
||||
request->write_buffer_send_offset = 0;
|
||||
response->total_size = request->response_write_position;
|
||||
return true;
|
||||
}
|
||||
{
|
||||
/* end of message, signal other side! */
|
||||
memcpy (request->write_buffer,
|
||||
"0\r\n",
|
||||
3);
|
||||
request->write_buffer_append_offset = 3;
|
||||
request->write_buffer_send_offset = 0;
|
||||
response->total_size = request->response_write_position;
|
||||
return true;
|
||||
}
|
||||
if (0 == ret)
|
||||
{
|
||||
request->state = MHD_REQUEST_CHUNKED_BODY_UNREADY;
|
||||
MHD_mutex_unlock_chk_ (&response->mutex);
|
||||
return false;
|
||||
}
|
||||
{
|
||||
request->state = MHD_REQUEST_CHUNKED_BODY_UNREADY;
|
||||
MHD_mutex_unlock_chk_ (&response->mutex);
|
||||
return false;
|
||||
}
|
||||
if (ret > 0xFFFFFF)
|
||||
ret = 0xFFFFFF;
|
||||
cblen = MHD_snprintf_(cbuf,
|
||||
sizeof (cbuf),
|
||||
"%X\r\n",
|
||||
(unsigned int) ret);
|
||||
mhd_assert(cblen > 0);
|
||||
mhd_assert((size_t)cblen < sizeof(cbuf));
|
||||
cblen = MHD_snprintf_ (cbuf,
|
||||
sizeof (cbuf),
|
||||
"%X\r\n",
|
||||
(unsigned int) ret);
|
||||
mhd_assert (cblen > 0);
|
||||
mhd_assert ((size_t) cblen < sizeof(cbuf));
|
||||
memcpy (&request->write_buffer[sizeof (cbuf) - cblen],
|
||||
cbuf,
|
||||
cblen);
|
||||
@@ -768,221 +779,224 @@ MHD_request_handle_write_ (struct MHD_Request *request)
|
||||
struct MHD_TLS_Plugin *tls;
|
||||
|
||||
if ( (NULL != (tls = daemon->tls_api)) &&
|
||||
(! tls->handshake (tls->cls,
|
||||
connection->tls_cs)) )
|
||||
(! tls->handshake (tls->cls,
|
||||
connection->tls_cs)) )
|
||||
return;
|
||||
}
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
|
||||
#if DEBUG_STATES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_STATE_MACHINE_STATUS_REPORT,
|
||||
_("In function %s handling connection at state: %s\n"),
|
||||
MHD_SC_STATE_MACHINE_STATUS_REPORT,
|
||||
_ ("In function %s handling connection at state: %s\n"),
|
||||
__FUNCTION__,
|
||||
MHD_state_to_string (request->state));
|
||||
#endif
|
||||
switch (request->state)
|
||||
{
|
||||
case MHD_REQUEST_INIT:
|
||||
case MHD_REQUEST_URL_RECEIVED:
|
||||
case MHD_REQUEST_HEADER_PART_RECEIVED:
|
||||
case MHD_REQUEST_HEADERS_RECEIVED:
|
||||
mhd_assert (0);
|
||||
return;
|
||||
case MHD_REQUEST_HEADERS_PROCESSED:
|
||||
return;
|
||||
case MHD_REQUEST_CONTINUE_SENDING:
|
||||
ret = connection->send_cls (connection,
|
||||
&HTTP_100_CONTINUE
|
||||
[request->continue_message_write_offset],
|
||||
MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE)
|
||||
- request->continue_message_write_offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
case MHD_REQUEST_INIT:
|
||||
case MHD_REQUEST_URL_RECEIVED:
|
||||
case MHD_REQUEST_HEADER_PART_RECEIVED:
|
||||
case MHD_REQUEST_HEADERS_RECEIVED:
|
||||
mhd_assert (0);
|
||||
return;
|
||||
case MHD_REQUEST_HEADERS_PROCESSED:
|
||||
return;
|
||||
case MHD_REQUEST_CONTINUE_SENDING:
|
||||
ret = connection->send_cls (connection,
|
||||
&HTTP_100_CONTINUE
|
||||
[request->continue_message_write_offset],
|
||||
MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE) -
|
||||
request->continue_message_write_offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (MHD_ERR_AGAIN_ == ret)
|
||||
return;
|
||||
if (MHD_ERR_AGAIN_ == ret)
|
||||
return;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
|
||||
_("Failed to send data in request for %s.\n"),
|
||||
request->url);
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
|
||||
_ ("Failed to send data in request for %s.\n"),
|
||||
request->url);
|
||||
#endif
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
request->continue_message_write_offset += ret;
|
||||
MHD_connection_update_last_activity_ (connection);
|
||||
return;
|
||||
case MHD_REQUEST_CONTINUE_SENT:
|
||||
case MHD_REQUEST_BODY_RECEIVED:
|
||||
case MHD_REQUEST_FOOTER_PART_RECEIVED:
|
||||
case MHD_REQUEST_FOOTERS_RECEIVED:
|
||||
mhd_assert (0);
|
||||
return;
|
||||
case MHD_REQUEST_HEADERS_SENDING:
|
||||
ret = connection->send_cls (connection,
|
||||
&request->write_buffer
|
||||
[request->write_buffer_send_offset],
|
||||
request->write_buffer_append_offset -
|
||||
request->write_buffer_send_offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (MHD_ERR_AGAIN_ == ret)
|
||||
return;
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
|
||||
_("Connection was closed while sending response headers.\n"));
|
||||
return;
|
||||
}
|
||||
request->write_buffer_send_offset += ret;
|
||||
MHD_connection_update_last_activity_ (connection);
|
||||
if (MHD_REQUEST_HEADERS_SENDING != request->state)
|
||||
return;
|
||||
check_write_done (request,
|
||||
MHD_REQUEST_HEADERS_SENT);
|
||||
return;
|
||||
case MHD_REQUEST_HEADERS_SENT:
|
||||
return;
|
||||
case MHD_REQUEST_NORMAL_BODY_READY:
|
||||
response = request->response;
|
||||
if (request->response_write_position <
|
||||
request->response->total_size)
|
||||
{
|
||||
uint64_t data_write_offset;
|
||||
|
||||
if (NULL != response->crc)
|
||||
MHD_mutex_lock_chk_ (&response->mutex);
|
||||
if (! try_ready_normal_body (request))
|
||||
{
|
||||
/* mutex was already unlocked by try_ready_normal_body */
|
||||
return;
|
||||
}
|
||||
#if defined(_MHD_HAVE_SENDFILE)
|
||||
if (MHD_resp_sender_sendfile == request->resp_sender)
|
||||
{
|
||||
ret = sendfile_adapter (connection);
|
||||
}
|
||||
else
|
||||
#else /* ! _MHD_HAVE_SENDFILE */
|
||||
if (1)
|
||||
#endif /* ! _MHD_HAVE_SENDFILE */
|
||||
{
|
||||
data_write_offset = request->response_write_position
|
||||
- response->data_start;
|
||||
if (data_write_offset > (uint64_t)SIZE_MAX)
|
||||
MHD_PANIC (_("Data offset exceeds limit"));
|
||||
ret = connection->send_cls (connection,
|
||||
&response->data
|
||||
[(size_t)data_write_offset],
|
||||
response->data_size -
|
||||
(size_t)data_write_offset);
|
||||
#if DEBUG_SEND_DATA
|
||||
if (ret > 0)
|
||||
fprintf (stderr,
|
||||
_("Sent %d-byte DATA response: `%.*s'\n"),
|
||||
(int) ret,
|
||||
(int) ret,
|
||||
&response->data[request->response_write_position -
|
||||
response->data_start]);
|
||||
#endif
|
||||
}
|
||||
if (NULL != response->crc)
|
||||
MHD_mutex_unlock_chk_ (&response->mutex);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (MHD_ERR_AGAIN_ == ret)
|
||||
return;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
|
||||
_("Failed to send data in request for `%s'.\n"),
|
||||
request->url);
|
||||
#endif
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
request->response_write_position += ret;
|
||||
MHD_connection_update_last_activity_ (connection);
|
||||
}
|
||||
if (request->response_write_position ==
|
||||
request->response->total_size)
|
||||
request->state = MHD_REQUEST_FOOTERS_SENT; /* have no footers */
|
||||
return;
|
||||
case MHD_REQUEST_NORMAL_BODY_UNREADY:
|
||||
mhd_assert (0);
|
||||
return;
|
||||
case MHD_REQUEST_CHUNKED_BODY_READY:
|
||||
ret = connection->send_cls (connection,
|
||||
&request->write_buffer
|
||||
[request->write_buffer_send_offset],
|
||||
request->write_buffer_append_offset -
|
||||
request->write_buffer_send_offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (MHD_ERR_AGAIN_ == ret)
|
||||
return;
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
|
||||
_("Connection was closed while sending response body.\n"));
|
||||
return;
|
||||
}
|
||||
request->write_buffer_send_offset += ret;
|
||||
MHD_connection_update_last_activity_ (connection);
|
||||
if (MHD_REQUEST_CHUNKED_BODY_READY != request->state)
|
||||
return;
|
||||
check_write_done (request,
|
||||
(request->response->total_size ==
|
||||
request->response_write_position) ?
|
||||
MHD_REQUEST_BODY_SENT :
|
||||
MHD_REQUEST_CHUNKED_BODY_UNREADY);
|
||||
return;
|
||||
case MHD_REQUEST_CHUNKED_BODY_UNREADY:
|
||||
case MHD_REQUEST_BODY_SENT:
|
||||
mhd_assert (0);
|
||||
return;
|
||||
case MHD_REQUEST_FOOTERS_SENDING:
|
||||
ret = connection->send_cls (connection,
|
||||
&request->write_buffer
|
||||
[request->write_buffer_send_offset],
|
||||
request->write_buffer_append_offset -
|
||||
request->write_buffer_send_offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (MHD_ERR_AGAIN_ == ret)
|
||||
return;
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
|
||||
_("Connection was closed while sending response body.\n"));
|
||||
return;
|
||||
}
|
||||
request->write_buffer_send_offset += ret;
|
||||
MHD_connection_update_last_activity_ (connection);
|
||||
if (MHD_REQUEST_FOOTERS_SENDING != request->state)
|
||||
return;
|
||||
check_write_done (request,
|
||||
MHD_REQUEST_FOOTERS_SENT);
|
||||
return;
|
||||
case MHD_REQUEST_FOOTERS_SENT:
|
||||
mhd_assert (0);
|
||||
return;
|
||||
case MHD_REQUEST_CLOSED:
|
||||
return;
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
case MHD_REQUEST_UPGRADE:
|
||||
mhd_assert (0);
|
||||
return;
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
default:
|
||||
mhd_assert (0);
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_STATEMACHINE_FAILURE_CONNECTION_CLOSED,
|
||||
_("Internal error\n"));
|
||||
break;
|
||||
MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
request->continue_message_write_offset += ret;
|
||||
MHD_connection_update_last_activity_ (connection);
|
||||
return;
|
||||
case MHD_REQUEST_CONTINUE_SENT:
|
||||
case MHD_REQUEST_BODY_RECEIVED:
|
||||
case MHD_REQUEST_FOOTER_PART_RECEIVED:
|
||||
case MHD_REQUEST_FOOTERS_RECEIVED:
|
||||
mhd_assert (0);
|
||||
return;
|
||||
case MHD_REQUEST_HEADERS_SENDING:
|
||||
ret = connection->send_cls (connection,
|
||||
&request->write_buffer
|
||||
[request->write_buffer_send_offset],
|
||||
request->write_buffer_append_offset
|
||||
- request->write_buffer_send_offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (MHD_ERR_AGAIN_ == ret)
|
||||
return;
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
|
||||
_ (
|
||||
"Connection was closed while sending response headers.\n"));
|
||||
return;
|
||||
}
|
||||
request->write_buffer_send_offset += ret;
|
||||
MHD_connection_update_last_activity_ (connection);
|
||||
if (MHD_REQUEST_HEADERS_SENDING != request->state)
|
||||
return;
|
||||
check_write_done (request,
|
||||
MHD_REQUEST_HEADERS_SENT);
|
||||
return;
|
||||
case MHD_REQUEST_HEADERS_SENT:
|
||||
return;
|
||||
case MHD_REQUEST_NORMAL_BODY_READY:
|
||||
response = request->response;
|
||||
if (request->response_write_position <
|
||||
request->response->total_size)
|
||||
{
|
||||
uint64_t data_write_offset;
|
||||
|
||||
if (NULL != response->crc)
|
||||
MHD_mutex_lock_chk_ (&response->mutex);
|
||||
if (! try_ready_normal_body (request))
|
||||
{
|
||||
/* mutex was already unlocked by try_ready_normal_body */
|
||||
return;
|
||||
}
|
||||
#if defined(_MHD_HAVE_SENDFILE)
|
||||
if (MHD_resp_sender_sendfile == request->resp_sender)
|
||||
{
|
||||
ret = sendfile_adapter (connection);
|
||||
}
|
||||
else
|
||||
#else /* ! _MHD_HAVE_SENDFILE */
|
||||
if (1)
|
||||
#endif /* ! _MHD_HAVE_SENDFILE */
|
||||
{
|
||||
data_write_offset = request->response_write_position
|
||||
- response->data_start;
|
||||
if (data_write_offset > (uint64_t) SIZE_MAX)
|
||||
MHD_PANIC (_ ("Data offset exceeds limit"));
|
||||
ret = connection->send_cls (connection,
|
||||
&response->data
|
||||
[(size_t) data_write_offset],
|
||||
response->data_size
|
||||
- (size_t) data_write_offset);
|
||||
#if DEBUG_SEND_DATA
|
||||
if (ret > 0)
|
||||
fprintf (stderr,
|
||||
_ ("Sent %d-byte DATA response: `%.*s'\n"),
|
||||
(int) ret,
|
||||
(int) ret,
|
||||
&response->data[request->response_write_position
|
||||
- response->data_start]);
|
||||
#endif
|
||||
}
|
||||
if (NULL != response->crc)
|
||||
MHD_mutex_unlock_chk_ (&response->mutex);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (MHD_ERR_AGAIN_ == ret)
|
||||
return;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
|
||||
_ ("Failed to send data in request for `%s'.\n"),
|
||||
request->url);
|
||||
#endif
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
request->response_write_position += ret;
|
||||
MHD_connection_update_last_activity_ (connection);
|
||||
}
|
||||
if (request->response_write_position ==
|
||||
request->response->total_size)
|
||||
request->state = MHD_REQUEST_FOOTERS_SENT; /* have no footers */
|
||||
return;
|
||||
case MHD_REQUEST_NORMAL_BODY_UNREADY:
|
||||
mhd_assert (0);
|
||||
return;
|
||||
case MHD_REQUEST_CHUNKED_BODY_READY:
|
||||
ret = connection->send_cls (connection,
|
||||
&request->write_buffer
|
||||
[request->write_buffer_send_offset],
|
||||
request->write_buffer_append_offset
|
||||
- request->write_buffer_send_offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (MHD_ERR_AGAIN_ == ret)
|
||||
return;
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
|
||||
_ (
|
||||
"Connection was closed while sending response body.\n"));
|
||||
return;
|
||||
}
|
||||
request->write_buffer_send_offset += ret;
|
||||
MHD_connection_update_last_activity_ (connection);
|
||||
if (MHD_REQUEST_CHUNKED_BODY_READY != request->state)
|
||||
return;
|
||||
check_write_done (request,
|
||||
(request->response->total_size ==
|
||||
request->response_write_position) ?
|
||||
MHD_REQUEST_BODY_SENT :
|
||||
MHD_REQUEST_CHUNKED_BODY_UNREADY);
|
||||
return;
|
||||
case MHD_REQUEST_CHUNKED_BODY_UNREADY:
|
||||
case MHD_REQUEST_BODY_SENT:
|
||||
mhd_assert (0);
|
||||
return;
|
||||
case MHD_REQUEST_FOOTERS_SENDING:
|
||||
ret = connection->send_cls (connection,
|
||||
&request->write_buffer
|
||||
[request->write_buffer_send_offset],
|
||||
request->write_buffer_append_offset
|
||||
- request->write_buffer_send_offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (MHD_ERR_AGAIN_ == ret)
|
||||
return;
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
|
||||
_ (
|
||||
"Connection was closed while sending response body.\n"));
|
||||
return;
|
||||
}
|
||||
request->write_buffer_send_offset += ret;
|
||||
MHD_connection_update_last_activity_ (connection);
|
||||
if (MHD_REQUEST_FOOTERS_SENDING != request->state)
|
||||
return;
|
||||
check_write_done (request,
|
||||
MHD_REQUEST_FOOTERS_SENT);
|
||||
return;
|
||||
case MHD_REQUEST_FOOTERS_SENT:
|
||||
mhd_assert (0);
|
||||
return;
|
||||
case MHD_REQUEST_CLOSED:
|
||||
return;
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
case MHD_REQUEST_UPGRADE:
|
||||
mhd_assert (0);
|
||||
return;
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
default:
|
||||
mhd_assert (0);
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_STATEMACHINE_FAILURE_CONNECTION_CLOSED,
|
||||
_ ("Internal error\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1001,9 +1015,9 @@ MHD_request_handle_write_ (struct MHD_Request *request)
|
||||
*/
|
||||
static bool
|
||||
MHD_lookup_header_token_ci (const struct MHD_Request *request,
|
||||
const char *header,
|
||||
const char *token,
|
||||
size_t token_len)
|
||||
const char *header,
|
||||
const char *token,
|
||||
size_t token_len)
|
||||
{
|
||||
struct MHD_HTTP_Header *pos;
|
||||
|
||||
@@ -1014,16 +1028,16 @@ MHD_lookup_header_token_ci (const struct MHD_Request *request,
|
||||
(0 == token[0]) )
|
||||
return false;
|
||||
for (pos = request->headers_received; NULL != pos; pos = pos->next)
|
||||
{
|
||||
if ( (0 != (pos->kind & MHD_HEADER_KIND)) &&
|
||||
( (header == pos->header) ||
|
||||
(MHD_str_equal_caseless_(header,
|
||||
pos->header)) ) &&
|
||||
(MHD_str_has_token_caseless_ (pos->value,
|
||||
token,
|
||||
token_len)) )
|
||||
return true;
|
||||
}
|
||||
{
|
||||
if ( (0 != (pos->kind & MHD_HEADER_KIND)) &&
|
||||
( (header == pos->header) ||
|
||||
(MHD_str_equal_caseless_ (header,
|
||||
pos->header)) ) &&
|
||||
(MHD_str_has_token_caseless_ (pos->value,
|
||||
token,
|
||||
token_len)) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1040,7 +1054,7 @@ MHD_lookup_header_token_ci (const struct MHD_Request *request,
|
||||
* false otherwise
|
||||
*/
|
||||
#define MHD_lookup_header_s_token_ci(r,h,tkn) \
|
||||
MHD_lookup_header_token_ci((r),(h),(tkn),MHD_STATICSTR_LEN_(tkn))
|
||||
MHD_lookup_header_token_ci ((r),(h),(tkn),MHD_STATICSTR_LEN_ (tkn))
|
||||
|
||||
|
||||
/**
|
||||
@@ -1071,27 +1085,27 @@ keepalive_possible (struct MHD_Request *request)
|
||||
return false;
|
||||
|
||||
if (MHD_str_equal_caseless_ (request->version_s,
|
||||
MHD_HTTP_VERSION_1_1))
|
||||
{
|
||||
if (MHD_lookup_header_s_token_ci (request,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"upgrade"))
|
||||
return false;
|
||||
if (MHD_lookup_header_s_token_ci (request,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"close"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (MHD_str_equal_caseless_ (request->version_s,
|
||||
MHD_HTTP_VERSION_1_0))
|
||||
{
|
||||
if (MHD_lookup_header_s_token_ci (request,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"Keep-Alive"))
|
||||
return true;
|
||||
MHD_HTTP_VERSION_1_1))
|
||||
{
|
||||
if (MHD_lookup_header_s_token_ci (request,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"upgrade"))
|
||||
return false;
|
||||
}
|
||||
if (MHD_lookup_header_s_token_ci (request,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"close"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (MHD_str_equal_caseless_ (request->version_s,
|
||||
MHD_HTTP_VERSION_1_0))
|
||||
{
|
||||
if (MHD_lookup_header_s_token_ci (request,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"Keep-Alive"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1105,7 +1119,7 @@ keepalive_possible (struct MHD_Request *request)
|
||||
*/
|
||||
static void
|
||||
get_date_string (char *date,
|
||||
size_t date_len)
|
||||
size_t date_len)
|
||||
{
|
||||
static const char *const days[] = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
@@ -1116,8 +1130,9 @@ get_date_string (char *date,
|
||||
};
|
||||
struct tm now;
|
||||
time_t t;
|
||||
#if !defined(HAVE_C11_GMTIME_S) && !defined(HAVE_W32_GMTIME_S) && !defined(HAVE_GMTIME_R)
|
||||
struct tm* pNow;
|
||||
#if ! defined(HAVE_C11_GMTIME_S) && ! defined(HAVE_W32_GMTIME_S) && \
|
||||
! defined(HAVE_GMTIME_R)
|
||||
struct tm*pNow;
|
||||
#endif
|
||||
|
||||
date[0] = 0;
|
||||
@@ -1131,25 +1146,25 @@ get_date_string (char *date,
|
||||
&t))
|
||||
return;
|
||||
#elif defined(HAVE_GMTIME_R)
|
||||
if (NULL == gmtime_r(&t,
|
||||
&now))
|
||||
if (NULL == gmtime_r (&t,
|
||||
&now))
|
||||
return;
|
||||
#else
|
||||
pNow = gmtime(&t);
|
||||
pNow = gmtime (&t);
|
||||
if (NULL == pNow)
|
||||
return;
|
||||
now = *pNow;
|
||||
#endif
|
||||
MHD_snprintf_ (date,
|
||||
date_len,
|
||||
"Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
|
||||
days[now.tm_wday % 7],
|
||||
(unsigned int) now.tm_mday,
|
||||
mons[now.tm_mon % 12],
|
||||
(unsigned int) (1900 + now.tm_year),
|
||||
(unsigned int) now.tm_hour,
|
||||
(unsigned int) now.tm_min,
|
||||
(unsigned int) now.tm_sec);
|
||||
date_len,
|
||||
"Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
|
||||
days[now.tm_wday % 7],
|
||||
(unsigned int) now.tm_mday,
|
||||
mons[now.tm_mon % 12],
|
||||
(unsigned int) (1900 + now.tm_year),
|
||||
(unsigned int) now.tm_hour,
|
||||
(unsigned int) now.tm_min,
|
||||
(unsigned int) now.tm_sec);
|
||||
}
|
||||
|
||||
|
||||
@@ -1168,9 +1183,9 @@ get_date_string (char *date,
|
||||
*/
|
||||
static bool
|
||||
check_response_header_token_ci (const struct MHD_Response *response,
|
||||
const char *key,
|
||||
const char *token,
|
||||
size_t token_len)
|
||||
const char *key,
|
||||
const char *token,
|
||||
size_t token_len)
|
||||
{
|
||||
struct MHD_HTTP_Header *pos;
|
||||
|
||||
@@ -1183,15 +1198,15 @@ check_response_header_token_ci (const struct MHD_Response *response,
|
||||
for (pos = response->first_header;
|
||||
NULL != pos;
|
||||
pos = pos->next)
|
||||
{
|
||||
if ( (pos->kind == MHD_HEADER_KIND) &&
|
||||
MHD_str_equal_caseless_ (pos->header,
|
||||
key) &&
|
||||
MHD_str_has_token_caseless_ (pos->value,
|
||||
token,
|
||||
token_len) )
|
||||
return true;
|
||||
}
|
||||
{
|
||||
if ( (pos->kind == MHD_HEADER_KIND) &&
|
||||
MHD_str_equal_caseless_ (pos->header,
|
||||
key) &&
|
||||
MHD_str_has_token_caseless_ (pos->value,
|
||||
token,
|
||||
token_len) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1208,7 +1223,7 @@ check_response_header_token_ci (const struct MHD_Response *response,
|
||||
* false otherwise
|
||||
*/
|
||||
#define check_response_header_s_token_ci(r,k,tkn) \
|
||||
check_response_header_token_ci((r),(k),(tkn),MHD_STATICSTR_LEN_(tkn))
|
||||
check_response_header_token_ci ((r),(k),(tkn),MHD_STATICSTR_LEN_ (tkn))
|
||||
|
||||
|
||||
/**
|
||||
@@ -1248,58 +1263,58 @@ build_header_response (struct MHD_Request *request)
|
||||
|
||||
mhd_assert (NULL != request->version_s);
|
||||
if (0 == request->version_s[0])
|
||||
{
|
||||
data = MHD_pool_allocate (connection->pool,
|
||||
0,
|
||||
MHD_YES);
|
||||
request->write_buffer = data;
|
||||
request->write_buffer_append_offset = 0;
|
||||
request->write_buffer_send_offset = 0;
|
||||
request->write_buffer_size = 0;
|
||||
return true;
|
||||
}
|
||||
{
|
||||
data = MHD_pool_allocate (connection->pool,
|
||||
0,
|
||||
MHD_YES);
|
||||
request->write_buffer = data;
|
||||
request->write_buffer_append_offset = 0;
|
||||
request->write_buffer_send_offset = 0;
|
||||
request->write_buffer_size = 0;
|
||||
return true;
|
||||
}
|
||||
if (MHD_REQUEST_FOOTERS_RECEIVED == request->state)
|
||||
{
|
||||
const char *reason_phrase;
|
||||
const char *version;
|
||||
{
|
||||
const char *reason_phrase;
|
||||
const char *version;
|
||||
|
||||
reason_phrase
|
||||
= MHD_get_reason_phrase_for (response->status_code);
|
||||
version
|
||||
= (response->icy)
|
||||
? "ICY"
|
||||
: ( (MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_0,
|
||||
request->version_s))
|
||||
? MHD_HTTP_VERSION_1_0
|
||||
: MHD_HTTP_VERSION_1_1);
|
||||
MHD_snprintf_ (code,
|
||||
sizeof (code),
|
||||
"%s %u %s\r\n",
|
||||
version,
|
||||
response->status_code,
|
||||
reason_phrase);
|
||||
off = strlen (code);
|
||||
/* estimate size */
|
||||
size = off + 2; /* +2 for extra "\r\n" at the end */
|
||||
kind = MHD_HEADER_KIND;
|
||||
if ( (! daemon->suppress_date) &&
|
||||
(NULL == MHD_response_get_header (response,
|
||||
MHD_HTTP_HEADER_DATE)) )
|
||||
get_date_string (date,
|
||||
sizeof (date));
|
||||
else
|
||||
date[0] = '\0';
|
||||
datelen = strlen (date);
|
||||
size += datelen;
|
||||
}
|
||||
reason_phrase
|
||||
= MHD_get_reason_phrase_for (response->status_code);
|
||||
version
|
||||
= (response->icy)
|
||||
? "ICY"
|
||||
: ( (MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_0,
|
||||
request->version_s))
|
||||
? MHD_HTTP_VERSION_1_0
|
||||
: MHD_HTTP_VERSION_1_1);
|
||||
MHD_snprintf_ (code,
|
||||
sizeof (code),
|
||||
"%s %u %s\r\n",
|
||||
version,
|
||||
response->status_code,
|
||||
reason_phrase);
|
||||
off = strlen (code);
|
||||
/* estimate size */
|
||||
size = off + 2; /* +2 for extra "\r\n" at the end */
|
||||
kind = MHD_HEADER_KIND;
|
||||
if ( (! daemon->suppress_date) &&
|
||||
(NULL == MHD_response_get_header (response,
|
||||
MHD_HTTP_HEADER_DATE)) )
|
||||
get_date_string (date,
|
||||
sizeof (date));
|
||||
else
|
||||
date[0] = '\0';
|
||||
datelen = strlen (date);
|
||||
size += datelen;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 2 bytes for final CRLF of a Chunked-Body */
|
||||
size = 2;
|
||||
kind = MHD_FOOTER_KIND;
|
||||
off = 0;
|
||||
datelen = 0;
|
||||
}
|
||||
{
|
||||
/* 2 bytes for final CRLF of a Chunked-Body */
|
||||
size = 2;
|
||||
kind = MHD_FOOTER_KIND;
|
||||
off = 0;
|
||||
datelen = 0;
|
||||
}
|
||||
|
||||
/* calculate extra headers we need to add, such as 'Connection: close',
|
||||
first see what was explicitly requested by the application */
|
||||
@@ -1309,153 +1324,154 @@ build_header_response (struct MHD_Request *request)
|
||||
must_add_content_length = false;
|
||||
response_has_close = false;
|
||||
switch (request->state)
|
||||
{
|
||||
case MHD_REQUEST_FOOTERS_RECEIVED:
|
||||
response_has_close
|
||||
= check_response_header_s_token_ci (response,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"close");
|
||||
response_has_keepalive
|
||||
= check_response_header_s_token_ci (response,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"Keep-Alive");
|
||||
client_requested_close
|
||||
= MHD_lookup_header_s_token_ci (request,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"close");
|
||||
|
||||
if (response->v10_only)
|
||||
request->keepalive = MHD_CONN_MUST_CLOSE;
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
else if (NULL != response->upgrade_handler)
|
||||
/* If this connection will not be "upgraded", it must be closed. */
|
||||
request->keepalive = MHD_CONN_MUST_CLOSE;
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
|
||||
/* now analyze chunked encoding situation */
|
||||
request->have_chunked_upload = false;
|
||||
|
||||
if ( (MHD_SIZE_UNKNOWN == response->total_size) &&
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
(NULL == response->upgrade_handler) &&
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
(! response_has_close) &&
|
||||
(! client_requested_close) )
|
||||
{
|
||||
case MHD_REQUEST_FOOTERS_RECEIVED:
|
||||
response_has_close
|
||||
= check_response_header_s_token_ci (response,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"close");
|
||||
response_has_keepalive
|
||||
= check_response_header_s_token_ci (response,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"Keep-Alive");
|
||||
client_requested_close
|
||||
= MHD_lookup_header_s_token_ci (request,
|
||||
MHD_HTTP_HEADER_CONNECTION,
|
||||
"close");
|
||||
|
||||
if (response->v10_only)
|
||||
request->keepalive = MHD_CONN_MUST_CLOSE;
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
else if (NULL != response->upgrade_handler)
|
||||
/* If this connection will not be "upgraded", it must be closed. */
|
||||
request->keepalive = MHD_CONN_MUST_CLOSE;
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
|
||||
/* now analyze chunked encoding situation */
|
||||
request->have_chunked_upload = false;
|
||||
|
||||
if ( (MHD_SIZE_UNKNOWN == response->total_size) &&
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
(NULL == response->upgrade_handler) &&
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
(! response_has_close) &&
|
||||
(! client_requested_close) )
|
||||
/* size is unknown, and close was not explicitly requested;
|
||||
need to either to HTTP 1.1 chunked encoding or
|
||||
close the connection */
|
||||
/* 'close' header doesn't exist yet, see if we need to add one;
|
||||
if the client asked for a close, no need to start chunk'ing */
|
||||
if ( (keepalive_possible (request)) &&
|
||||
(MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_1,
|
||||
request->version_s)) )
|
||||
{
|
||||
have_encoding
|
||||
= MHD_response_get_header (response,
|
||||
MHD_HTTP_HEADER_TRANSFER_ENCODING);
|
||||
if (NULL == have_encoding)
|
||||
{
|
||||
/* size is unknown, and close was not explicitly requested;
|
||||
need to either to HTTP 1.1 chunked encoding or
|
||||
close the connection */
|
||||
/* 'close' header doesn't exist yet, see if we need to add one;
|
||||
if the client asked for a close, no need to start chunk'ing */
|
||||
if ( (keepalive_possible (request)) &&
|
||||
(MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_1,
|
||||
request->version_s)) )
|
||||
{
|
||||
have_encoding
|
||||
= MHD_response_get_header (response,
|
||||
MHD_HTTP_HEADER_TRANSFER_ENCODING);
|
||||
if (NULL == have_encoding)
|
||||
{
|
||||
must_add_chunked_encoding = true;
|
||||
request->have_chunked_upload = true;
|
||||
}
|
||||
else if (MHD_str_equal_caseless_ (have_encoding,
|
||||
"identity"))
|
||||
{
|
||||
/* application forced identity encoding, can't do 'chunked' */
|
||||
must_add_close = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
request->have_chunked_upload = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Keep alive or chunking not possible
|
||||
=> set close header if not present */
|
||||
if (! response_has_close)
|
||||
must_add_close = true;
|
||||
}
|
||||
must_add_chunked_encoding = true;
|
||||
request->have_chunked_upload = true;
|
||||
}
|
||||
|
||||
/* check for other reasons to add 'close' header */
|
||||
if ( ( (client_requested_close) ||
|
||||
(connection->read_closed) ||
|
||||
(MHD_CONN_MUST_CLOSE == request->keepalive)) &&
|
||||
(! response_has_close) &&
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
(NULL == response->upgrade_handler) &&
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
(! response->v10_only) )
|
||||
must_add_close = true;
|
||||
|
||||
/* check if we should add a 'content length' header */
|
||||
have_content_length
|
||||
= MHD_response_get_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_LENGTH);
|
||||
|
||||
/* MHD_HTTP_NO_CONTENT, MHD_HTTP_NOT_MODIFIED and 1xx-status
|
||||
codes SHOULD NOT have a Content-Length according to spec;
|
||||
also chunked encoding / unknown length or CONNECT... */
|
||||
if ( (MHD_SIZE_UNKNOWN != response->total_size) &&
|
||||
(MHD_HTTP_NO_CONTENT != response->status_code) &&
|
||||
(MHD_HTTP_NOT_MODIFIED != response->status_code) &&
|
||||
(MHD_HTTP_OK <= response->status_code) &&
|
||||
(NULL == have_content_length) &&
|
||||
(request->method != MHD_METHOD_CONNECT) )
|
||||
else if (MHD_str_equal_caseless_ (have_encoding,
|
||||
"identity"))
|
||||
{
|
||||
/*
|
||||
Here we add a content-length if one is missing; however,
|
||||
for 'connect' methods, the responses MUST NOT include a
|
||||
content-length header *if* the response code is 2xx (in
|
||||
which case we expect there to be no body). Still,
|
||||
as we don't know the response code here in some cases, we
|
||||
simply only force adding a content-length header if this
|
||||
is not a 'connect' or if the response is not empty
|
||||
(which is kind of more sane, because if some crazy
|
||||
application did return content with a 2xx status code,
|
||||
then having a content-length might again be a good idea).
|
||||
|
||||
Note that the change from 'SHOULD NOT' to 'MUST NOT' is
|
||||
a recent development of the HTTP 1.1 specification.
|
||||
*/
|
||||
content_length_len
|
||||
= MHD_snprintf_ (content_length_buf,
|
||||
sizeof (content_length_buf),
|
||||
MHD_HTTP_HEADER_CONTENT_LENGTH ": " MHD_UNSIGNED_LONG_LONG_PRINTF "\r\n",
|
||||
(MHD_UNSIGNED_LONG_LONG) response->total_size);
|
||||
must_add_content_length = true;
|
||||
/* application forced identity encoding, can't do 'chunked' */
|
||||
must_add_close = true;
|
||||
}
|
||||
|
||||
/* check for adding keep alive */
|
||||
if ( (! response_has_keepalive) &&
|
||||
(! response_has_close) &&
|
||||
(! must_add_close) &&
|
||||
(MHD_CONN_MUST_CLOSE != request->keepalive) &&
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
(NULL == response->upgrade_handler) &&
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
(keepalive_possible (request)) )
|
||||
must_add_keep_alive = true;
|
||||
break;
|
||||
case MHD_REQUEST_BODY_SENT:
|
||||
response_has_keepalive = false;
|
||||
break;
|
||||
default:
|
||||
mhd_assert (0);
|
||||
return MHD_NO;
|
||||
else
|
||||
{
|
||||
request->have_chunked_upload = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Keep alive or chunking not possible
|
||||
=> set close header if not present */
|
||||
if (! response_has_close)
|
||||
must_add_close = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for other reasons to add 'close' header */
|
||||
if ( ( (client_requested_close) ||
|
||||
(connection->read_closed) ||
|
||||
(MHD_CONN_MUST_CLOSE == request->keepalive)) &&
|
||||
(! response_has_close) &&
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
(NULL == response->upgrade_handler) &&
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
(! response->v10_only) )
|
||||
must_add_close = true;
|
||||
|
||||
/* check if we should add a 'content length' header */
|
||||
have_content_length
|
||||
= MHD_response_get_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_LENGTH);
|
||||
|
||||
/* MHD_HTTP_NO_CONTENT, MHD_HTTP_NOT_MODIFIED and 1xx-status
|
||||
codes SHOULD NOT have a Content-Length according to spec;
|
||||
also chunked encoding / unknown length or CONNECT... */
|
||||
if ( (MHD_SIZE_UNKNOWN != response->total_size) &&
|
||||
(MHD_HTTP_NO_CONTENT != response->status_code) &&
|
||||
(MHD_HTTP_NOT_MODIFIED != response->status_code) &&
|
||||
(MHD_HTTP_OK <= response->status_code) &&
|
||||
(NULL == have_content_length) &&
|
||||
(request->method != MHD_METHOD_CONNECT) )
|
||||
{
|
||||
/*
|
||||
Here we add a content-length if one is missing; however,
|
||||
for 'connect' methods, the responses MUST NOT include a
|
||||
content-length header *if* the response code is 2xx (in
|
||||
which case we expect there to be no body). Still,
|
||||
as we don't know the response code here in some cases, we
|
||||
simply only force adding a content-length header if this
|
||||
is not a 'connect' or if the response is not empty
|
||||
(which is kind of more sane, because if some crazy
|
||||
application did return content with a 2xx status code,
|
||||
then having a content-length might again be a good idea).
|
||||
|
||||
Note that the change from 'SHOULD NOT' to 'MUST NOT' is
|
||||
a recent development of the HTTP 1.1 specification.
|
||||
*/
|
||||
content_length_len
|
||||
= MHD_snprintf_ (content_length_buf,
|
||||
sizeof (content_length_buf),
|
||||
MHD_HTTP_HEADER_CONTENT_LENGTH ": "
|
||||
MHD_UNSIGNED_LONG_LONG_PRINTF "\r\n",
|
||||
(MHD_UNSIGNED_LONG_LONG) response->total_size);
|
||||
must_add_content_length = true;
|
||||
}
|
||||
|
||||
/* check for adding keep alive */
|
||||
if ( (! response_has_keepalive) &&
|
||||
(! response_has_close) &&
|
||||
(! must_add_close) &&
|
||||
(MHD_CONN_MUST_CLOSE != request->keepalive) &&
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
(NULL == response->upgrade_handler) &&
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
(keepalive_possible (request)) )
|
||||
must_add_keep_alive = true;
|
||||
break;
|
||||
case MHD_REQUEST_BODY_SENT:
|
||||
response_has_keepalive = false;
|
||||
break;
|
||||
default:
|
||||
mhd_assert (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
if (MHD_CONN_MUST_CLOSE != request->keepalive)
|
||||
{
|
||||
if ( (must_add_close) ||
|
||||
(response_has_close) )
|
||||
request->keepalive = MHD_CONN_MUST_CLOSE;
|
||||
else if ( (must_add_keep_alive) ||
|
||||
(response_has_keepalive) )
|
||||
request->keepalive = MHD_CONN_USE_KEEPALIVE;
|
||||
}
|
||||
{
|
||||
if ( (must_add_close) ||
|
||||
(response_has_close) )
|
||||
request->keepalive = MHD_CONN_MUST_CLOSE;
|
||||
else if ( (must_add_keep_alive) ||
|
||||
(response_has_keepalive) )
|
||||
request->keepalive = MHD_CONN_USE_KEEPALIVE;
|
||||
}
|
||||
|
||||
if (must_add_close)
|
||||
size += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
|
||||
@@ -1469,91 +1485,91 @@ build_header_response (struct MHD_Request *request)
|
||||
mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
|
||||
|
||||
for (pos = response->first_header; NULL != pos; pos = pos->next)
|
||||
{
|
||||
/* TODO: add proper support for excluding "Keep-Alive" token. */
|
||||
if ( (pos->kind == kind) &&
|
||||
(! ( (must_add_close) &&
|
||||
(response_has_keepalive) &&
|
||||
(MHD_str_equal_caseless_(pos->header,
|
||||
MHD_HTTP_HEADER_CONNECTION)) &&
|
||||
(MHD_str_equal_caseless_(pos->value,
|
||||
"Keep-Alive")) ) ) )
|
||||
size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
|
||||
}
|
||||
{
|
||||
/* TODO: add proper support for excluding "Keep-Alive" token. */
|
||||
if ( (pos->kind == kind) &&
|
||||
(! ( (must_add_close) &&
|
||||
(response_has_keepalive) &&
|
||||
(MHD_str_equal_caseless_ (pos->header,
|
||||
MHD_HTTP_HEADER_CONNECTION)) &&
|
||||
(MHD_str_equal_caseless_ (pos->value,
|
||||
"Keep-Alive")) ) ) )
|
||||
size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
|
||||
}
|
||||
/* produce data */
|
||||
data = MHD_pool_allocate (connection->pool,
|
||||
size + 1,
|
||||
MHD_NO);
|
||||
if (NULL == data)
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
|
||||
"Not enough memory for write!\n");
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
|
||||
"Not enough memory for write!\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (MHD_REQUEST_FOOTERS_RECEIVED == request->state)
|
||||
{
|
||||
memcpy (data,
|
||||
code,
|
||||
off);
|
||||
}
|
||||
{
|
||||
memcpy (data,
|
||||
code,
|
||||
off);
|
||||
}
|
||||
if (must_add_close)
|
||||
{
|
||||
/* we must add the 'Connection: close' header */
|
||||
memcpy (&data[off],
|
||||
"Connection: close\r\n",
|
||||
MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
|
||||
off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
|
||||
}
|
||||
{
|
||||
/* we must add the 'Connection: close' header */
|
||||
memcpy (&data[off],
|
||||
"Connection: close\r\n",
|
||||
MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
|
||||
off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
|
||||
}
|
||||
if (must_add_keep_alive)
|
||||
{
|
||||
/* we must add the 'Connection: Keep-Alive' header */
|
||||
memcpy (&data[off],
|
||||
"Connection: Keep-Alive\r\n",
|
||||
MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
|
||||
off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
|
||||
}
|
||||
{
|
||||
/* we must add the 'Connection: Keep-Alive' header */
|
||||
memcpy (&data[off],
|
||||
"Connection: Keep-Alive\r\n",
|
||||
MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
|
||||
off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
|
||||
}
|
||||
if (must_add_chunked_encoding)
|
||||
{
|
||||
/* we must add the 'Transfer-Encoding: chunked' header */
|
||||
memcpy (&data[off],
|
||||
"Transfer-Encoding: chunked\r\n",
|
||||
MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
|
||||
off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
|
||||
}
|
||||
{
|
||||
/* we must add the 'Transfer-Encoding: chunked' header */
|
||||
memcpy (&data[off],
|
||||
"Transfer-Encoding: chunked\r\n",
|
||||
MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
|
||||
off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
|
||||
}
|
||||
if (must_add_content_length)
|
||||
{
|
||||
/* we must add the 'Content-Length' header */
|
||||
memcpy (&data[off],
|
||||
content_length_buf,
|
||||
content_length_len);
|
||||
off += content_length_len;
|
||||
}
|
||||
{
|
||||
/* we must add the 'Content-Length' header */
|
||||
memcpy (&data[off],
|
||||
content_length_buf,
|
||||
content_length_len);
|
||||
off += content_length_len;
|
||||
}
|
||||
for (pos = response->first_header; NULL != pos; pos = pos->next)
|
||||
{
|
||||
/* TODO: add proper support for excluding "Keep-Alive" token. */
|
||||
if ( (pos->kind == kind) &&
|
||||
(! ( (must_add_close) &&
|
||||
(response_has_keepalive) &&
|
||||
(MHD_str_equal_caseless_(pos->header,
|
||||
MHD_HTTP_HEADER_CONNECTION)) &&
|
||||
(MHD_str_equal_caseless_(pos->value,
|
||||
"Keep-Alive")) ) ) )
|
||||
off += MHD_snprintf_ (&data[off],
|
||||
size - off,
|
||||
"%s: %s\r\n",
|
||||
pos->header,
|
||||
pos->value);
|
||||
}
|
||||
{
|
||||
/* TODO: add proper support for excluding "Keep-Alive" token. */
|
||||
if ( (pos->kind == kind) &&
|
||||
(! ( (must_add_close) &&
|
||||
(response_has_keepalive) &&
|
||||
(MHD_str_equal_caseless_ (pos->header,
|
||||
MHD_HTTP_HEADER_CONNECTION)) &&
|
||||
(MHD_str_equal_caseless_ (pos->value,
|
||||
"Keep-Alive")) ) ) )
|
||||
off += MHD_snprintf_ (&data[off],
|
||||
size - off,
|
||||
"%s: %s\r\n",
|
||||
pos->header,
|
||||
pos->value);
|
||||
}
|
||||
if (MHD_REQUEST_FOOTERS_RECEIVED == request->state)
|
||||
{
|
||||
memcpy (&data[off],
|
||||
date,
|
||||
datelen);
|
||||
off += datelen;
|
||||
}
|
||||
{
|
||||
memcpy (&data[off],
|
||||
date,
|
||||
datelen);
|
||||
off += datelen;
|
||||
}
|
||||
memcpy (&data[off],
|
||||
"\r\n",
|
||||
2);
|
||||
@@ -1584,50 +1600,52 @@ build_header_response (struct MHD_Request *request)
|
||||
*/
|
||||
static void
|
||||
transmit_error_response (struct MHD_Request *request,
|
||||
enum MHD_StatusCode ec,
|
||||
enum MHD_StatusCode ec,
|
||||
enum MHD_HTTP_StatusCode status_code,
|
||||
const char *message)
|
||||
const char *message)
|
||||
{
|
||||
struct MHD_Response *response;
|
||||
|
||||
if (NULL == request->version_s)
|
||||
{
|
||||
/* we were unable to process the full header line, so we don't
|
||||
really know what version the client speaks; assume 1.0 */
|
||||
request->version_s = MHD_HTTP_VERSION_1_0;
|
||||
}
|
||||
{
|
||||
/* we were unable to process the full header line, so we don't
|
||||
really know what version the client speaks; assume 1.0 */
|
||||
request->version_s = MHD_HTTP_VERSION_1_0;
|
||||
}
|
||||
request->state = MHD_REQUEST_FOOTERS_RECEIVED;
|
||||
request->connection->read_closed = true;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (request->daemon,
|
||||
ec,
|
||||
_("Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
|
||||
ec,
|
||||
_ (
|
||||
"Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
|
||||
status_code,
|
||||
message);
|
||||
#endif
|
||||
if (NULL != request->response)
|
||||
{
|
||||
MHD_response_queue_for_destroy (request->response);
|
||||
request->response = NULL;
|
||||
}
|
||||
{
|
||||
MHD_response_queue_for_destroy (request->response);
|
||||
request->response = NULL;
|
||||
}
|
||||
response = MHD_response_from_buffer (status_code,
|
||||
strlen (message),
|
||||
(void *) message,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
strlen (message),
|
||||
(void *) message,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
request->response = response;
|
||||
/* Do not reuse this connection. */
|
||||
request->keepalive = MHD_CONN_MUST_CLOSE;
|
||||
if (! build_header_response (request))
|
||||
{
|
||||
/* oops - close! */
|
||||
CONNECTION_CLOSE_ERROR (request->connection,
|
||||
ec,
|
||||
_("Closing connection (failed to create response header)\n"));
|
||||
}
|
||||
{
|
||||
/* oops - close! */
|
||||
CONNECTION_CLOSE_ERROR (request->connection,
|
||||
ec,
|
||||
_ (
|
||||
"Closing connection (failed to create response header)\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
request->state = MHD_REQUEST_HEADERS_SENDING;
|
||||
}
|
||||
{
|
||||
request->state = MHD_REQUEST_HEADERS_SENDING;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1640,7 +1658,8 @@ transmit_error_response (struct MHD_Request *request,
|
||||
static enum MHD_Method
|
||||
method_string_to_enum (const char *method)
|
||||
{
|
||||
static const struct {
|
||||
static const struct
|
||||
{
|
||||
const char *key;
|
||||
enum MHD_Method value;
|
||||
} methods[] = {
|
||||
@@ -1685,10 +1704,10 @@ method_string_to_enum (const char *method)
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
for (i=0;NULL != methods[i].key;i++)
|
||||
for (i = 0; NULL != methods[i].key; i++)
|
||||
if (0 ==
|
||||
MHD_str_equal_caseless_ (method,
|
||||
methods[i].key))
|
||||
MHD_str_equal_caseless_ (method,
|
||||
methods[i].key))
|
||||
return methods[i].value;
|
||||
return MHD_METHOD_UNKNOWN;
|
||||
}
|
||||
@@ -1706,27 +1725,27 @@ method_string_to_enum (const char *method)
|
||||
*/
|
||||
static bool
|
||||
request_add_header (struct MHD_Request *request,
|
||||
const char *key,
|
||||
const char *value,
|
||||
enum MHD_ValueKind kind)
|
||||
const char *key,
|
||||
const char *value,
|
||||
enum MHD_ValueKind kind)
|
||||
{
|
||||
if (MHD_NO ==
|
||||
MHD_request_set_value (request,
|
||||
kind,
|
||||
key,
|
||||
value))
|
||||
{
|
||||
kind,
|
||||
key,
|
||||
value))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (request->daemon,
|
||||
MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
|
||||
_("Not enough memory in pool to allocate header record!\n"));
|
||||
MHD_DLOG (request->daemon,
|
||||
MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
|
||||
_ ("Not enough memory in pool to allocate header record!\n"));
|
||||
#endif
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CLIENT_HEADER_TOO_BIG,
|
||||
MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
|
||||
REQUEST_TOO_BIG);
|
||||
return false;
|
||||
}
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CLIENT_HEADER_TOO_BIG,
|
||||
MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
|
||||
REQUEST_TOO_BIG);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1763,76 +1782,76 @@ parse_initial_message_line (struct MHD_Request *request,
|
||||
/* Skip any spaces. Not required by standard but allow
|
||||
to be more tolerant. */
|
||||
while ( (' ' == uri[0]) &&
|
||||
( (size_t)(uri - line) < line_len) )
|
||||
( (size_t) (uri - line) < line_len) )
|
||||
uri++;
|
||||
if ((size_t)(uri - line) == line_len)
|
||||
{
|
||||
curi = "";
|
||||
uri = NULL;
|
||||
request->version_s = "";
|
||||
args = NULL;
|
||||
url_end = line_len - (line - uri); // EH, this is garbage. FIXME!
|
||||
}
|
||||
if ((size_t) (uri - line) == line_len)
|
||||
{
|
||||
curi = "";
|
||||
uri = NULL;
|
||||
request->version_s = "";
|
||||
args = NULL;
|
||||
url_end = line_len - (line - uri); // EH, this is garbage. FIXME!
|
||||
}
|
||||
else
|
||||
{
|
||||
curi = uri;
|
||||
/* Search from back to accept misformed URI with space */
|
||||
http_version = line + line_len - 1;
|
||||
/* Skip any trailing spaces */
|
||||
while ( (' ' == http_version[0]) &&
|
||||
(http_version > uri) )
|
||||
http_version--;
|
||||
/* Find first space in reverse direction */
|
||||
while ( (' ' != http_version[0]) &&
|
||||
(http_version > uri) )
|
||||
http_version--;
|
||||
if (http_version > uri)
|
||||
{
|
||||
curi = uri;
|
||||
/* Search from back to accept misformed URI with space */
|
||||
http_version = line + line_len - 1;
|
||||
/* Skip any trailing spaces */
|
||||
while ( (' ' == http_version[0]) &&
|
||||
(http_version > uri) )
|
||||
http_version--;
|
||||
/* Find first space in reverse direction */
|
||||
while ( (' ' != http_version[0]) &&
|
||||
(http_version > uri) )
|
||||
http_version--;
|
||||
if (http_version > uri)
|
||||
{
|
||||
http_version[0] = '\0';
|
||||
request->version_s = http_version + 1;
|
||||
args = memchr (uri,
|
||||
'?',
|
||||
http_version - uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
request->version_s = "";
|
||||
args = memchr (uri,
|
||||
'?',
|
||||
line_len - (uri - line));
|
||||
}
|
||||
url_end = http_version - uri;
|
||||
http_version[0] = '\0';
|
||||
request->version_s = http_version + 1;
|
||||
args = memchr (uri,
|
||||
'?',
|
||||
http_version - uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
request->version_s = "";
|
||||
args = memchr (uri,
|
||||
'?',
|
||||
line_len - (uri - line));
|
||||
}
|
||||
url_end = http_version - uri;
|
||||
}
|
||||
if ( (MHD_PSL_STRICT == daemon->protocol_strict_level) &&
|
||||
(NULL != memchr (curi,
|
||||
' ',
|
||||
url_end)) )
|
||||
{
|
||||
/* space exists in URI and we are supposed to be strict, reject */
|
||||
return MHD_NO;
|
||||
}
|
||||
{
|
||||
/* space exists in URI and we are supposed to be strict, reject */
|
||||
return MHD_NO;
|
||||
}
|
||||
if (NULL != daemon->early_uri_logger_cb)
|
||||
{
|
||||
request->client_context
|
||||
= daemon->early_uri_logger_cb (daemon->early_uri_logger_cb_cls,
|
||||
curi,
|
||||
request);
|
||||
}
|
||||
{
|
||||
request->client_context
|
||||
= daemon->early_uri_logger_cb (daemon->early_uri_logger_cb_cls,
|
||||
curi,
|
||||
request);
|
||||
}
|
||||
if (NULL != args)
|
||||
{
|
||||
args[0] = '\0';
|
||||
args++;
|
||||
/* note that this call clobbers 'args' */
|
||||
MHD_parse_arguments_ (request,
|
||||
MHD_GET_ARGUMENT_KIND,
|
||||
args,
|
||||
&request_add_header,
|
||||
&unused_num_headers);
|
||||
}
|
||||
{
|
||||
args[0] = '\0';
|
||||
args++;
|
||||
/* note that this call clobbers 'args' */
|
||||
MHD_parse_arguments_ (request,
|
||||
MHD_GET_ARGUMENT_KIND,
|
||||
args,
|
||||
&request_add_header,
|
||||
&unused_num_headers);
|
||||
}
|
||||
if (NULL != uri)
|
||||
daemon->unescape_cb (daemon->unescape_cb_cls,
|
||||
request,
|
||||
uri);
|
||||
request,
|
||||
uri);
|
||||
request->url = curi;
|
||||
return true;
|
||||
}
|
||||
@@ -1856,43 +1875,46 @@ process_header_line (struct MHD_Request *request,
|
||||
|
||||
/* line should be normal header line, find colon */
|
||||
colon = strchr (line,
|
||||
':');
|
||||
':');
|
||||
if (NULL == colon)
|
||||
{
|
||||
/* error in header line, die hard */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
|
||||
_ (
|
||||
"Received malformed line (no colon). Closing connection.\n"));
|
||||
return false;
|
||||
}
|
||||
if (MHD_PSL_PERMISSIVE != request->daemon->protocol_strict_level)
|
||||
{
|
||||
/* check for whitespace before colon, which is not allowed
|
||||
by RFC 7230 section 3.2.4; we count space ' ' and
|
||||
tab '\t', but not '\r\n' as those would have ended the line. */
|
||||
const char *white;
|
||||
|
||||
white = strchr (line,
|
||||
(unsigned char) ' ');
|
||||
if ( (NULL != white) &&
|
||||
(white < colon) )
|
||||
{
|
||||
/* error in header line, die hard */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
|
||||
_("Received malformed line (no colon). Closing connection.\n"));
|
||||
MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
|
||||
_ (
|
||||
"Whitespace before colon forbidden by RFC 7230. Closing connection.\n"));
|
||||
return false;
|
||||
}
|
||||
if (MHD_PSL_PERMISSIVE != request->daemon->protocol_strict_level)
|
||||
white = strchr (line,
|
||||
(unsigned char) '\t');
|
||||
if ( (NULL != white) &&
|
||||
(white < colon) )
|
||||
{
|
||||
/* check for whitespace before colon, which is not allowed
|
||||
by RFC 7230 section 3.2.4; we count space ' ' and
|
||||
tab '\t', but not '\r\n' as those would have ended the line. */
|
||||
const char *white;
|
||||
|
||||
white = strchr (line,
|
||||
(unsigned char) ' ');
|
||||
if ( (NULL != white) &&
|
||||
(white < colon) )
|
||||
{
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
|
||||
_("Whitespace before colon forbidden by RFC 7230. Closing connection.\n"));
|
||||
return false;
|
||||
}
|
||||
white = strchr (line,
|
||||
(unsigned char) '\t');
|
||||
if ( (NULL != white) &&
|
||||
(white < colon) )
|
||||
{
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
|
||||
_("Tab before colon forbidden by RFC 7230. Closing connection.\n"));
|
||||
return false;
|
||||
}
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
|
||||
_ (
|
||||
"Tab before colon forbidden by RFC 7230. Closing connection.\n"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* zero-terminate header */
|
||||
colon[0] = '\0';
|
||||
colon++; /* advance to value */
|
||||
@@ -1935,69 +1957,69 @@ process_broken_line (struct MHD_Request *request,
|
||||
last = request->last;
|
||||
if ( (' ' == line[0]) ||
|
||||
('\t' == line[0]) )
|
||||
{
|
||||
/* value was continued on the next line, see
|
||||
http://www.jmarshall.com/easy/http/ */
|
||||
last_len = strlen (last);
|
||||
/* skip whitespace at start of 2nd line */
|
||||
tmp = line;
|
||||
while ( (' ' == tmp[0]) ||
|
||||
('\t' == tmp[0]) )
|
||||
tmp++;
|
||||
tmp_len = strlen (tmp);
|
||||
/* FIXME: we might be able to do this better (faster!), as most
|
||||
likely 'last' and 'line' should already be adjacent in
|
||||
memory; however, doing this right gets tricky if we have a
|
||||
value continued over multiple lines (in which case we need to
|
||||
record how often we have done this so we can check for
|
||||
adjacency); also, in the case where these are not adjacent
|
||||
(not sure how it can happen!), we would want to allocate from
|
||||
the end of the pool, so as to not destroy the read-buffer's
|
||||
ability to grow nicely. */
|
||||
last = MHD_pool_reallocate (connection->pool,
|
||||
last,
|
||||
last_len + 1,
|
||||
last_len + tmp_len + 1);
|
||||
if (NULL == last)
|
||||
{
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CLIENT_HEADER_TOO_BIG,
|
||||
MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
|
||||
REQUEST_TOO_BIG);
|
||||
return MHD_NO;
|
||||
}
|
||||
memcpy (&last[last_len],
|
||||
tmp,
|
||||
tmp_len + 1);
|
||||
request->last = last;
|
||||
return MHD_YES; /* possibly more than 2 lines... */
|
||||
}
|
||||
mhd_assert ( (NULL != last) &&
|
||||
(NULL != request->colon) );
|
||||
if (! request_add_header (request,
|
||||
last,
|
||||
request->colon,
|
||||
kind))
|
||||
{
|
||||
/* value was continued on the next line, see
|
||||
http://www.jmarshall.com/easy/http/ */
|
||||
last_len = strlen (last);
|
||||
/* skip whitespace at start of 2nd line */
|
||||
tmp = line;
|
||||
while ( (' ' == tmp[0]) ||
|
||||
('\t' == tmp[0]) )
|
||||
tmp++;
|
||||
tmp_len = strlen (tmp);
|
||||
/* FIXME: we might be able to do this better (faster!), as most
|
||||
likely 'last' and 'line' should already be adjacent in
|
||||
memory; however, doing this right gets tricky if we have a
|
||||
value continued over multiple lines (in which case we need to
|
||||
record how often we have done this so we can check for
|
||||
adjacency); also, in the case where these are not adjacent
|
||||
(not sure how it can happen!), we would want to allocate from
|
||||
the end of the pool, so as to not destroy the read-buffer's
|
||||
ability to grow nicely. */
|
||||
last = MHD_pool_reallocate (connection->pool,
|
||||
last,
|
||||
last_len + 1,
|
||||
last_len + tmp_len + 1);
|
||||
if (NULL == last)
|
||||
{
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CLIENT_HEADER_TOO_BIG,
|
||||
MHD_SC_CLIENT_HEADER_TOO_BIG,
|
||||
MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
|
||||
REQUEST_TOO_BIG);
|
||||
return false;
|
||||
return MHD_NO;
|
||||
}
|
||||
memcpy (&last[last_len],
|
||||
tmp,
|
||||
tmp_len + 1);
|
||||
request->last = last;
|
||||
return MHD_YES; /* possibly more than 2 lines... */
|
||||
}
|
||||
mhd_assert ( (NULL != last) &&
|
||||
(NULL != request->colon) );
|
||||
if (! request_add_header (request,
|
||||
last,
|
||||
request->colon,
|
||||
kind))
|
||||
{
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CLIENT_HEADER_TOO_BIG,
|
||||
MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
|
||||
REQUEST_TOO_BIG);
|
||||
return false;
|
||||
}
|
||||
/* we still have the current line to deal with... */
|
||||
if ('\0' != line[0])
|
||||
{
|
||||
if (! process_header_line (request,
|
||||
line))
|
||||
{
|
||||
if (! process_header_line (request,
|
||||
line))
|
||||
{
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
REQUEST_MALFORMED);
|
||||
return false;
|
||||
}
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
REQUEST_MALFORMED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2032,22 +2054,22 @@ get_next_header_line (struct MHD_Request *request,
|
||||
pos++;
|
||||
if ( (pos == request->read_buffer_offset - 1) &&
|
||||
('\n' != rbuf[pos]) )
|
||||
{
|
||||
/* not found, consider growing... */
|
||||
if ( (request->read_buffer_offset == request->read_buffer_size) &&
|
||||
(! try_grow_read_buffer (request)) )
|
||||
{
|
||||
/* not found, consider growing... */
|
||||
if ( (request->read_buffer_offset == request->read_buffer_size) &&
|
||||
(! try_grow_read_buffer (request)) )
|
||||
{
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CLIENT_HEADER_TOO_BIG,
|
||||
(NULL != request->url)
|
||||
? MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
|
||||
: MHD_HTTP_URI_TOO_LONG,
|
||||
REQUEST_TOO_BIG);
|
||||
}
|
||||
if (line_len)
|
||||
*line_len = 0;
|
||||
return NULL;
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CLIENT_HEADER_TOO_BIG,
|
||||
(NULL != request->url)
|
||||
? MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
|
||||
: MHD_HTTP_URI_TOO_LONG,
|
||||
REQUEST_TOO_BIG);
|
||||
}
|
||||
if (line_len)
|
||||
*line_len = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (line_len)
|
||||
*line_len = pos;
|
||||
@@ -2083,7 +2105,7 @@ get_next_header_line (struct MHD_Request *request,
|
||||
* @return true if force push is possible, false otherwise
|
||||
*/
|
||||
static bool
|
||||
socket_flush_possible(struct MHD_Connection *connection)
|
||||
socket_flush_possible (struct MHD_Connection *connection)
|
||||
{
|
||||
(void) connection; /* Mute compiler warning. */
|
||||
#if defined(TCP_CORK) || defined(TCP_PUSH)
|
||||
@@ -2105,21 +2127,21 @@ static bool
|
||||
socket_start_extra_buffering (struct MHD_Connection *connection)
|
||||
{
|
||||
bool res = false;
|
||||
(void)connection; /* Mute compiler warning. */
|
||||
(void) connection; /* Mute compiler warning. */
|
||||
#if defined(TCP_CORK) || defined(TCP_NOPUSH)
|
||||
const MHD_SCKT_OPT_BOOL_ on_val = 1;
|
||||
#if defined(TCP_NODELAY)
|
||||
const MHD_SCKT_OPT_BOOL_ off_val = 0;
|
||||
#endif /* TCP_NODELAY */
|
||||
mhd_assert(NULL != connection);
|
||||
#if defined(TCP_NOPUSH) && !defined(TCP_CORK)
|
||||
mhd_assert (NULL != connection);
|
||||
#if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
|
||||
/* Buffer data before sending */
|
||||
res = (0 == setsockopt (connection->socket_fd,
|
||||
IPPROTO_TCP,
|
||||
TCP_NOPUSH,
|
||||
(const void *) &on_val,
|
||||
sizeof (on_val)))
|
||||
? true : false;
|
||||
? true : false;
|
||||
#if defined(TCP_NODELAY)
|
||||
/* Enable Nagle's algorithm */
|
||||
/* TCP_NODELAY may interfere with TCP_NOPUSH */
|
||||
@@ -2128,7 +2150,7 @@ socket_start_extra_buffering (struct MHD_Connection *connection)
|
||||
TCP_NODELAY,
|
||||
(const void *) &off_val,
|
||||
sizeof (off_val)))
|
||||
? true : false;
|
||||
? true : false;
|
||||
#endif /* TCP_NODELAY */
|
||||
#else /* TCP_CORK */
|
||||
#if defined(TCP_NODELAY)
|
||||
@@ -2147,7 +2169,7 @@ socket_start_extra_buffering (struct MHD_Connection *connection)
|
||||
TCP_CORK,
|
||||
(const void *) &on_val,
|
||||
sizeof (on_val)))
|
||||
? true : false;
|
||||
? true : false;
|
||||
#endif /* TCP_CORK */
|
||||
#endif /* TCP_CORK || TCP_NOPUSH */
|
||||
return res;
|
||||
@@ -2170,8 +2192,8 @@ socket_start_no_buffering (struct MHD_Connection *connection)
|
||||
const MHD_SCKT_OPT_BOOL_ off_val = 0;
|
||||
#endif /* TCP_CORK || TCP_NOPUSH */
|
||||
|
||||
(void)connection; /* Mute compiler warning. */
|
||||
mhd_assert(NULL != connection);
|
||||
(void) connection; /* Mute compiler warning. */
|
||||
mhd_assert (NULL != connection);
|
||||
#if defined(TCP_CORK)
|
||||
/* Allow partial packets */
|
||||
res &= (0 == setsockopt (connection->socket_fd,
|
||||
@@ -2179,7 +2201,7 @@ socket_start_no_buffering (struct MHD_Connection *connection)
|
||||
TCP_CORK,
|
||||
(const void *) &off_val,
|
||||
sizeof (off_val)))
|
||||
? true : false;
|
||||
? true : false;
|
||||
#endif /* TCP_CORK */
|
||||
#if defined(TCP_NODELAY)
|
||||
/* Disable Nagle's algorithm for sending packets without delay */
|
||||
@@ -2188,16 +2210,16 @@ socket_start_no_buffering (struct MHD_Connection *connection)
|
||||
TCP_NODELAY,
|
||||
(const void *) &on_val,
|
||||
sizeof (on_val)))
|
||||
? true : false;
|
||||
? true : false;
|
||||
#endif /* TCP_NODELAY */
|
||||
#if defined(TCP_NOPUSH) && !defined(TCP_CORK)
|
||||
#if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
|
||||
/* Disable extra buffering */
|
||||
res &= (0 == setsockopt (connection->socket_fd,
|
||||
IPPROTO_TCP,
|
||||
TCP_NOPUSH,
|
||||
(const void *) &off_val,
|
||||
sizeof (off_val)))
|
||||
? true : false;
|
||||
? true : false;
|
||||
#endif /* TCP_NOPUSH && !TCP_CORK */
|
||||
return res;
|
||||
#else /* !TCP_NODELAY */
|
||||
@@ -2217,21 +2239,21 @@ static bool
|
||||
socket_start_no_buffering_flush (struct MHD_Connection *connection)
|
||||
{
|
||||
bool res = true;
|
||||
#if defined(TCP_NOPUSH) && !defined(TCP_CORK)
|
||||
#if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
|
||||
const int dummy = 0;
|
||||
#endif /* !TCP_CORK */
|
||||
|
||||
if (NULL == connection)
|
||||
return false; /* FIXME: use MHD_NONNULL? */
|
||||
res = socket_start_no_buffering (connection);
|
||||
#if defined(TCP_NOPUSH) && !defined(TCP_CORK)
|
||||
#if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
|
||||
/* Force flush data with zero send otherwise Darwin and some BSD systems
|
||||
will add 5 seconds delay. Not required with TCP_CORK as switching off
|
||||
TCP_CORK always flushes socket buffer. */
|
||||
res &= (0 <= MHD_send_ (connection->socket_fd,
|
||||
&dummy,
|
||||
0))
|
||||
? true : false;
|
||||
? true : false;
|
||||
#endif /* TCP_NOPUSH && !TCP_CORK*/
|
||||
return res;
|
||||
}
|
||||
@@ -2254,7 +2276,7 @@ socket_start_normal_buffering (struct MHD_Connection *connection)
|
||||
socklen_t param_size = sizeof (cork_val);
|
||||
#endif /* TCP_CORK */
|
||||
|
||||
mhd_assert(NULL != connection);
|
||||
mhd_assert (NULL != connection);
|
||||
#if defined(TCP_CORK)
|
||||
/* Allow partial packets */
|
||||
/* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't enabled before
|
||||
@@ -2262,7 +2284,7 @@ socket_start_normal_buffering (struct MHD_Connection *connection)
|
||||
if ( (0 != getsockopt (connection->socket_fd,
|
||||
IPPROTO_TCP,
|
||||
TCP_CORK,
|
||||
(void*)&cork_val,
|
||||
(void*) &cork_val,
|
||||
¶m_size)) ||
|
||||
(0 != cork_val))
|
||||
res &= (0 == setsockopt (connection->socket_fd,
|
||||
@@ -2270,7 +2292,7 @@ socket_start_normal_buffering (struct MHD_Connection *connection)
|
||||
TCP_CORK,
|
||||
(const void *) &off_val,
|
||||
sizeof (off_val)))
|
||||
? true : false;
|
||||
? true : false;
|
||||
#elif defined(TCP_NOPUSH)
|
||||
/* Disable extra buffering */
|
||||
/* No need to check current value as disabling TCP_NOPUSH will not flush partial
|
||||
@@ -2280,7 +2302,7 @@ socket_start_normal_buffering (struct MHD_Connection *connection)
|
||||
TCP_NOPUSH,
|
||||
(const void *) &off_val,
|
||||
sizeof (off_val)))
|
||||
? true : false;
|
||||
? true : false;
|
||||
#endif /* TCP_NOPUSH && !TCP_CORK */
|
||||
/* Enable Nagle's algorithm for normal buffering */
|
||||
res &= (0 == setsockopt (connection->socket_fd,
|
||||
@@ -2288,7 +2310,7 @@ socket_start_normal_buffering (struct MHD_Connection *connection)
|
||||
TCP_NODELAY,
|
||||
(const void *) &off_val,
|
||||
sizeof (off_val)))
|
||||
? true : false;
|
||||
? true : false;
|
||||
return res;
|
||||
#else /* !TCP_NODELAY */
|
||||
return false;
|
||||
@@ -2309,16 +2331,17 @@ need_100_continue (struct MHD_Request *request)
|
||||
const char *expect;
|
||||
|
||||
return ( (NULL == request->response) &&
|
||||
(NULL != request->version_s) &&
|
||||
(MHD_str_equal_caseless_(request->version_s,
|
||||
MHD_HTTP_VERSION_1_1)) &&
|
||||
(NULL != (expect = MHD_request_lookup_value (request,
|
||||
MHD_HEADER_KIND,
|
||||
MHD_HTTP_HEADER_EXPECT))) &&
|
||||
(MHD_str_equal_caseless_(expect,
|
||||
"100-continue")) &&
|
||||
(request->continue_message_write_offset <
|
||||
MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE)) );
|
||||
(NULL != request->version_s) &&
|
||||
(MHD_str_equal_caseless_ (request->version_s,
|
||||
MHD_HTTP_VERSION_1_1)) &&
|
||||
(NULL != (expect = MHD_request_lookup_value (request,
|
||||
MHD_HEADER_KIND,
|
||||
MHD_HTTP_HEADER_EXPECT)))
|
||||
&&
|
||||
(MHD_str_equal_caseless_ (expect,
|
||||
"100-continue")) &&
|
||||
(request->continue_message_write_offset <
|
||||
MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE)) );
|
||||
}
|
||||
|
||||
|
||||
@@ -2342,94 +2365,94 @@ parse_cookie_header (struct MHD_Request *request)
|
||||
int quotes;
|
||||
|
||||
hdr = MHD_request_lookup_value (request,
|
||||
MHD_HEADER_KIND,
|
||||
MHD_HTTP_HEADER_COOKIE);
|
||||
MHD_HEADER_KIND,
|
||||
MHD_HTTP_HEADER_COOKIE);
|
||||
if (NULL == hdr)
|
||||
return true;
|
||||
cpy = MHD_pool_allocate (request->connection->pool,
|
||||
strlen (hdr) + 1,
|
||||
MHD_YES);
|
||||
if (NULL == cpy)
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (request->daemon,
|
||||
MHD_SC_COOKIE_POOL_ALLOCATION_FAILURE,
|
||||
_("Not enough memory in pool to parse cookies!\n"));
|
||||
MHD_DLOG (request->daemon,
|
||||
MHD_SC_COOKIE_POOL_ALLOCATION_FAILURE,
|
||||
_ ("Not enough memory in pool to parse cookies!\n"));
|
||||
#endif
|
||||
transmit_error_response (request,
|
||||
MHD_SC_COOKIE_POOL_ALLOCATION_FAILURE,
|
||||
MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
|
||||
REQUEST_TOO_BIG);
|
||||
return false;
|
||||
}
|
||||
transmit_error_response (request,
|
||||
MHD_SC_COOKIE_POOL_ALLOCATION_FAILURE,
|
||||
MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
|
||||
REQUEST_TOO_BIG);
|
||||
return false;
|
||||
}
|
||||
memcpy (cpy,
|
||||
hdr,
|
||||
strlen (hdr) + 1);
|
||||
pos = cpy;
|
||||
while (NULL != pos)
|
||||
{
|
||||
while (' ' == *pos)
|
||||
pos++; /* skip spaces */
|
||||
{
|
||||
while (' ' == *pos)
|
||||
pos++; /* skip spaces */
|
||||
|
||||
sce = pos;
|
||||
while ( ((*sce) != '\0') &&
|
||||
((*sce) != ',') &&
|
||||
((*sce) != ';') &&
|
||||
((*sce) != '=') )
|
||||
sce++;
|
||||
/* remove tailing whitespace (if any) from key */
|
||||
ekill = sce - 1;
|
||||
while ( (*ekill == ' ') &&
|
||||
(ekill >= pos) )
|
||||
*(ekill--) = '\0';
|
||||
old = *sce;
|
||||
*sce = '\0';
|
||||
if (old != '=')
|
||||
{
|
||||
/* value part omitted, use empty string... */
|
||||
if (! request_add_header (request,
|
||||
pos,
|
||||
"",
|
||||
MHD_COOKIE_KIND))
|
||||
return false;
|
||||
if (old == '\0')
|
||||
break;
|
||||
pos = sce + 1;
|
||||
continue;
|
||||
}
|
||||
equals = sce + 1;
|
||||
quotes = 0;
|
||||
semicolon = equals;
|
||||
while ( ('\0' != semicolon[0]) &&
|
||||
( (0 != quotes) ||
|
||||
( (';' != semicolon[0]) &&
|
||||
(',' != semicolon[0]) ) ) )
|
||||
{
|
||||
if ('"' == semicolon[0])
|
||||
quotes = (quotes + 1) & 1;
|
||||
semicolon++;
|
||||
}
|
||||
if ('\0' == semicolon[0])
|
||||
semicolon = NULL;
|
||||
if (NULL != semicolon)
|
||||
{
|
||||
semicolon[0] = '\0';
|
||||
semicolon++;
|
||||
}
|
||||
/* remove quotes */
|
||||
if ( ('"' == equals[0]) &&
|
||||
('"' == equals[strlen (equals) - 1]) )
|
||||
{
|
||||
equals[strlen (equals) - 1] = '\0';
|
||||
equals++;
|
||||
}
|
||||
sce = pos;
|
||||
while ( ((*sce) != '\0') &&
|
||||
((*sce) != ',') &&
|
||||
((*sce) != ';') &&
|
||||
((*sce) != '=') )
|
||||
sce++;
|
||||
/* remove tailing whitespace (if any) from key */
|
||||
ekill = sce - 1;
|
||||
while ( (*ekill == ' ') &&
|
||||
(ekill >= pos) )
|
||||
*(ekill--) = '\0';
|
||||
old = *sce;
|
||||
*sce = '\0';
|
||||
if (old != '=')
|
||||
{
|
||||
/* value part omitted, use empty string... */
|
||||
if (! request_add_header (request,
|
||||
pos,
|
||||
equals,
|
||||
MHD_COOKIE_KIND))
|
||||
pos,
|
||||
"",
|
||||
MHD_COOKIE_KIND))
|
||||
return false;
|
||||
pos = semicolon;
|
||||
if (old == '\0')
|
||||
break;
|
||||
pos = sce + 1;
|
||||
continue;
|
||||
}
|
||||
equals = sce + 1;
|
||||
quotes = 0;
|
||||
semicolon = equals;
|
||||
while ( ('\0' != semicolon[0]) &&
|
||||
( (0 != quotes) ||
|
||||
( (';' != semicolon[0]) &&
|
||||
(',' != semicolon[0]) ) ) )
|
||||
{
|
||||
if ('"' == semicolon[0])
|
||||
quotes = (quotes + 1) & 1;
|
||||
semicolon++;
|
||||
}
|
||||
if ('\0' == semicolon[0])
|
||||
semicolon = NULL;
|
||||
if (NULL != semicolon)
|
||||
{
|
||||
semicolon[0] = '\0';
|
||||
semicolon++;
|
||||
}
|
||||
/* remove quotes */
|
||||
if ( ('"' == equals[0]) &&
|
||||
('"' == equals[strlen (equals) - 1]) )
|
||||
{
|
||||
equals[strlen (equals) - 1] = '\0';
|
||||
equals++;
|
||||
}
|
||||
if (! request_add_header (request,
|
||||
pos,
|
||||
equals,
|
||||
MHD_COOKIE_KIND))
|
||||
return false;
|
||||
pos = semicolon;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2454,64 +2477,64 @@ parse_request_headers (struct MHD_Request *request)
|
||||
parse_cookie_header (request); /* FIXME: return value ignored! */
|
||||
if ( (MHD_PSL_STRICT == daemon->protocol_strict_level) &&
|
||||
(NULL != request->version_s) &&
|
||||
(MHD_str_equal_caseless_(MHD_HTTP_VERSION_1_1,
|
||||
request->version_s)) &&
|
||||
(MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_1,
|
||||
request->version_s)) &&
|
||||
(NULL ==
|
||||
MHD_request_lookup_value (request,
|
||||
MHD_HEADER_KIND,
|
||||
MHD_HTTP_HEADER_HOST)) )
|
||||
{
|
||||
/* die, http 1.1 request without host and we are pedantic */
|
||||
request->state = MHD_REQUEST_FOOTERS_RECEIVED;
|
||||
connection->read_closed = true;
|
||||
MHD_HEADER_KIND,
|
||||
MHD_HTTP_HEADER_HOST)) )
|
||||
{
|
||||
/* die, http 1.1 request without host and we are pedantic */
|
||||
request->state = MHD_REQUEST_FOOTERS_RECEIVED;
|
||||
connection->read_closed = true;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_HOST_HEADER_MISSING,
|
||||
_("Received HTTP 1.1 request without `Host' header.\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_HOST_HEADER_MISSING,
|
||||
_ ("Received HTTP 1.1 request without `Host' header.\n"));
|
||||
#endif
|
||||
mhd_assert (NULL == request->response);
|
||||
response =
|
||||
MHD_response_from_buffer (MHD_HTTP_BAD_REQUEST,
|
||||
MHD_STATICSTR_LEN_ (REQUEST_LACKS_HOST),
|
||||
REQUEST_LACKS_HOST,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
request->response = response;
|
||||
// FIXME: state machine advance?
|
||||
return;
|
||||
}
|
||||
mhd_assert (NULL == request->response);
|
||||
response =
|
||||
MHD_response_from_buffer (MHD_HTTP_BAD_REQUEST,
|
||||
MHD_STATICSTR_LEN_ (REQUEST_LACKS_HOST),
|
||||
REQUEST_LACKS_HOST,
|
||||
MHD_RESPMEM_PERSISTENT);
|
||||
request->response = response;
|
||||
// FIXME: state machine advance?
|
||||
return;
|
||||
}
|
||||
|
||||
request->remaining_upload_size = 0;
|
||||
enc = MHD_request_lookup_value (request,
|
||||
MHD_HEADER_KIND,
|
||||
MHD_HTTP_HEADER_TRANSFER_ENCODING);
|
||||
MHD_HEADER_KIND,
|
||||
MHD_HTTP_HEADER_TRANSFER_ENCODING);
|
||||
if (NULL != enc)
|
||||
{
|
||||
request->remaining_upload_size = MHD_SIZE_UNKNOWN;
|
||||
if (MHD_str_equal_caseless_ (enc,
|
||||
"chunked"))
|
||||
request->have_chunked_upload = true;
|
||||
return;
|
||||
}
|
||||
{
|
||||
request->remaining_upload_size = MHD_SIZE_UNKNOWN;
|
||||
if (MHD_str_equal_caseless_ (enc,
|
||||
"chunked"))
|
||||
request->have_chunked_upload = true;
|
||||
return;
|
||||
}
|
||||
clen = MHD_request_lookup_value (request,
|
||||
MHD_HEADER_KIND,
|
||||
MHD_HTTP_HEADER_CONTENT_LENGTH);
|
||||
MHD_HEADER_KIND,
|
||||
MHD_HTTP_HEADER_CONTENT_LENGTH);
|
||||
if (NULL == clen)
|
||||
return;
|
||||
end = clen + MHD_str_to_uint64_ (clen,
|
||||
&request->remaining_upload_size);
|
||||
&request->remaining_upload_size);
|
||||
if ( (clen == end) ||
|
||||
('\0' != *end) )
|
||||
{
|
||||
request->remaining_upload_size = 0;
|
||||
{
|
||||
request->remaining_upload_size = 0;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (request->daemon,
|
||||
MHD_SC_CONTENT_LENGTH_MALFORMED,
|
||||
"Failed to parse `Content-Length' header. Closing connection.\n");
|
||||
MHD_DLOG (request->daemon,
|
||||
MHD_SC_CONTENT_LENGTH_MALFORMED,
|
||||
"Failed to parse `Content-Length' header. Closing connection.\n");
|
||||
#endif
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONTENT_LENGTH_MALFORMED,
|
||||
NULL);
|
||||
}
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONTENT_LENGTH_MALFORMED,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2531,19 +2554,20 @@ call_request_handler (struct MHD_Request *request)
|
||||
if (NULL != request->response)
|
||||
return; /* already queued a response */
|
||||
if (NULL == (action =
|
||||
daemon->rc (daemon->rc_cls,
|
||||
request,
|
||||
request->url,
|
||||
request->method)))
|
||||
{
|
||||
/* serious internal error, close connection */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_APPLICATION_CALLBACK_FAILURE_CLOSED,
|
||||
_("Application reported internal error, closing connection.\n"));
|
||||
return;
|
||||
}
|
||||
daemon->rc (daemon->rc_cls,
|
||||
request,
|
||||
request->url,
|
||||
request->method)))
|
||||
{
|
||||
/* serious internal error, close connection */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_APPLICATION_CALLBACK_FAILURE_CLOSED,
|
||||
_ (
|
||||
"Application reported internal error, closing connection.\n"));
|
||||
return;
|
||||
}
|
||||
action->action (action->action_cls,
|
||||
request);
|
||||
request);
|
||||
}
|
||||
|
||||
|
||||
@@ -2568,208 +2592,212 @@ process_request_body (struct MHD_Request *request)
|
||||
buffer_head = request->read_buffer;
|
||||
available = request->read_buffer_offset;
|
||||
do
|
||||
{
|
||||
size_t to_be_processed;
|
||||
size_t left_unprocessed;
|
||||
size_t processed_size;
|
||||
|
||||
instant_retry = false;
|
||||
if ( (request->have_chunked_upload) &&
|
||||
(MHD_SIZE_UNKNOWN == request->remaining_upload_size) )
|
||||
{
|
||||
size_t to_be_processed;
|
||||
size_t left_unprocessed;
|
||||
size_t processed_size;
|
||||
if ( (request->current_chunk_offset == request->current_chunk_size) &&
|
||||
(0LLU != request->current_chunk_offset) &&
|
||||
(available >= 2) )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
instant_retry = false;
|
||||
if ( (request->have_chunked_upload) &&
|
||||
(MHD_SIZE_UNKNOWN == request->remaining_upload_size) )
|
||||
/* skip new line at the *end* of a chunk */
|
||||
i = 0;
|
||||
if ( ('\r' == buffer_head[i]) ||
|
||||
('\n' == buffer_head[i]) )
|
||||
i++; /* skip 1st part of line feed */
|
||||
if ( ('\r' == buffer_head[i]) ||
|
||||
('\n' == buffer_head[i]) )
|
||||
i++; /* skip 2nd part of line feed */
|
||||
if (0 == i)
|
||||
{
|
||||
if ( (request->current_chunk_offset == request->current_chunk_size) &&
|
||||
(0LLU != request->current_chunk_offset) &&
|
||||
(available >= 2) )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* skip new line at the *end* of a chunk */
|
||||
i = 0;
|
||||
if ( ('\r' == buffer_head[i]) ||
|
||||
('\n' == buffer_head[i]) )
|
||||
i++; /* skip 1st part of line feed */
|
||||
if ( ('\r' == buffer_head[i]) ||
|
||||
('\n' == buffer_head[i]) )
|
||||
i++; /* skip 2nd part of line feed */
|
||||
if (0 == i)
|
||||
{
|
||||
/* malformed encoding */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CHUNKED_ENCODING_MALFORMED,
|
||||
_("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
|
||||
return;
|
||||
}
|
||||
available -= i;
|
||||
buffer_head += i;
|
||||
request->current_chunk_offset = 0;
|
||||
request->current_chunk_size = 0;
|
||||
}
|
||||
if (request->current_chunk_offset <
|
||||
request->current_chunk_size)
|
||||
{
|
||||
uint64_t cur_chunk_left;
|
||||
|
||||
/* we are in the middle of a chunk, give
|
||||
as much as possible to the client (without
|
||||
crossing chunk boundaries) */
|
||||
cur_chunk_left
|
||||
= request->current_chunk_size - request->current_chunk_offset;
|
||||
if (cur_chunk_left > available)
|
||||
{
|
||||
to_be_processed = available;
|
||||
}
|
||||
else
|
||||
{ /* cur_chunk_left <= (size_t)available */
|
||||
to_be_processed = (size_t)cur_chunk_left;
|
||||
if (available > to_be_processed)
|
||||
instant_retry = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t i;
|
||||
size_t end_size;
|
||||
bool malformed;
|
||||
|
||||
/* we need to read chunk boundaries */
|
||||
i = 0;
|
||||
while (i < available)
|
||||
{
|
||||
if ( ('\r' == buffer_head[i]) ||
|
||||
('\n' == buffer_head[i]) ||
|
||||
(';' == buffer_head[i]) )
|
||||
break;
|
||||
i++;
|
||||
if (i >= 16)
|
||||
break;
|
||||
}
|
||||
end_size = i;
|
||||
/* find beginning of CRLF (skip over chunk extensions) */
|
||||
if (';' == buffer_head[i])
|
||||
{
|
||||
while (i < available)
|
||||
{
|
||||
if ( ('\r' == buffer_head[i]) ||
|
||||
('\n' == buffer_head[i]) )
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
/* take '\n' into account; if '\n' is the unavailable
|
||||
character, we will need to wait until we have it
|
||||
before going further */
|
||||
if ( (i + 1 >= available) &&
|
||||
! ( (1 == i) &&
|
||||
(2 == available) &&
|
||||
('0' == buffer_head[0]) ) )
|
||||
break; /* need more data... */
|
||||
i++;
|
||||
malformed = (end_size >= 16);
|
||||
if (! malformed)
|
||||
{
|
||||
size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
|
||||
end_size,
|
||||
&request->current_chunk_size);
|
||||
malformed = (end_size != num_dig);
|
||||
}
|
||||
if (malformed)
|
||||
{
|
||||
/* malformed encoding */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CHUNKED_ENCODING_MALFORMED,
|
||||
_("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
|
||||
return;
|
||||
}
|
||||
/* skip 2nd part of line feed */
|
||||
if ( (i < available) &&
|
||||
( ('\r' == buffer_head[i]) ||
|
||||
('\n' == buffer_head[i]) ) )
|
||||
i++;
|
||||
|
||||
buffer_head += i;
|
||||
available -= i;
|
||||
request->current_chunk_offset = 0;
|
||||
|
||||
if (available > 0)
|
||||
instant_retry = true;
|
||||
if (0LLU == request->current_chunk_size)
|
||||
{
|
||||
request->remaining_upload_size = 0;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no chunked encoding, give all to the client */
|
||||
if ( (0 != request->remaining_upload_size) &&
|
||||
(MHD_SIZE_UNKNOWN != request->remaining_upload_size) &&
|
||||
(request->remaining_upload_size < available) )
|
||||
{
|
||||
to_be_processed = (size_t)request->remaining_upload_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* 1. no chunked encoding, give all to the client
|
||||
* 2. client may send large chunked data, but only a smaller part is available at one time.
|
||||
*/
|
||||
to_be_processed = available;
|
||||
}
|
||||
}
|
||||
left_unprocessed = to_be_processed;
|
||||
#if FIXME_OLD_STYLE
|
||||
if (MHD_NO ==
|
||||
daemon->rc (daemon->rc_cls,
|
||||
request,
|
||||
request->url,
|
||||
request->method,
|
||||
request->version,
|
||||
buffer_head,
|
||||
&left_unprocessed,
|
||||
&request->client_context))
|
||||
{
|
||||
/* serious internal error, close connection */
|
||||
/* malformed encoding */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_APPLICATION_CALLBACK_FAILURE_CLOSED,
|
||||
_("Application reported internal error, closing connection.\n"));
|
||||
MHD_SC_CHUNKED_ENCODING_MALFORMED,
|
||||
_ (
|
||||
"Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (left_unprocessed > to_be_processed)
|
||||
mhd_panic (mhd_panic_cls,
|
||||
__FILE__,
|
||||
__LINE__
|
||||
#ifdef HAVE_MESSAGES
|
||||
, _("libmicrohttpd API violation")
|
||||
#else
|
||||
, NULL
|
||||
#endif
|
||||
);
|
||||
if (0 != left_unprocessed)
|
||||
{
|
||||
instant_retry = false; /* client did not process everything */
|
||||
#ifdef HAVE_MESSAGES
|
||||
/* client did not process all upload data, complain if
|
||||
the setup was incorrect, which may prevent us from
|
||||
handling the rest of the request */
|
||||
if ( (MHD_TM_EXTERNAL_EVENT_LOOP == daemon->threading_mode) &&
|
||||
(! connection->suspended) )
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_APPLICATION_HUNG_CONNECTION,
|
||||
_("WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
|
||||
#endif
|
||||
}
|
||||
processed_size = to_be_processed - left_unprocessed;
|
||||
if (request->have_chunked_upload)
|
||||
request->current_chunk_offset += processed_size;
|
||||
/* dh left "processed" bytes in buffer for next time... */
|
||||
buffer_head += processed_size;
|
||||
available -= processed_size;
|
||||
if (MHD_SIZE_UNKNOWN != request->remaining_upload_size)
|
||||
request->remaining_upload_size -= processed_size;
|
||||
available -= i;
|
||||
buffer_head += i;
|
||||
request->current_chunk_offset = 0;
|
||||
request->current_chunk_size = 0;
|
||||
}
|
||||
if (request->current_chunk_offset <
|
||||
request->current_chunk_size)
|
||||
{
|
||||
uint64_t cur_chunk_left;
|
||||
|
||||
/* we are in the middle of a chunk, give
|
||||
as much as possible to the client (without
|
||||
crossing chunk boundaries) */
|
||||
cur_chunk_left
|
||||
= request->current_chunk_size - request->current_chunk_offset;
|
||||
if (cur_chunk_left > available)
|
||||
{
|
||||
to_be_processed = available;
|
||||
}
|
||||
else
|
||||
{ /* cur_chunk_left <= (size_t)available */
|
||||
to_be_processed = (size_t) cur_chunk_left;
|
||||
if (available > to_be_processed)
|
||||
instant_retry = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t i;
|
||||
size_t end_size;
|
||||
bool malformed;
|
||||
|
||||
/* we need to read chunk boundaries */
|
||||
i = 0;
|
||||
while (i < available)
|
||||
{
|
||||
if ( ('\r' == buffer_head[i]) ||
|
||||
('\n' == buffer_head[i]) ||
|
||||
(';' == buffer_head[i]) )
|
||||
break;
|
||||
i++;
|
||||
if (i >= 16)
|
||||
break;
|
||||
}
|
||||
end_size = i;
|
||||
/* find beginning of CRLF (skip over chunk extensions) */
|
||||
if (';' == buffer_head[i])
|
||||
{
|
||||
while (i < available)
|
||||
{
|
||||
if ( ('\r' == buffer_head[i]) ||
|
||||
('\n' == buffer_head[i]) )
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
/* take '\n' into account; if '\n' is the unavailable
|
||||
character, we will need to wait until we have it
|
||||
before going further */
|
||||
if ( (i + 1 >= available) &&
|
||||
! ( (1 == i) &&
|
||||
(2 == available) &&
|
||||
('0' == buffer_head[0]) ) )
|
||||
break; /* need more data... */
|
||||
i++;
|
||||
malformed = (end_size >= 16);
|
||||
if (! malformed)
|
||||
{
|
||||
size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
|
||||
end_size,
|
||||
&request->current_chunk_size);
|
||||
malformed = (end_size != num_dig);
|
||||
}
|
||||
if (malformed)
|
||||
{
|
||||
/* malformed encoding */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CHUNKED_ENCODING_MALFORMED,
|
||||
_ (
|
||||
"Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
|
||||
return;
|
||||
}
|
||||
/* skip 2nd part of line feed */
|
||||
if ( (i < available) &&
|
||||
( ('\r' == buffer_head[i]) ||
|
||||
('\n' == buffer_head[i]) ) )
|
||||
i++;
|
||||
|
||||
buffer_head += i;
|
||||
available -= i;
|
||||
request->current_chunk_offset = 0;
|
||||
|
||||
if (available > 0)
|
||||
instant_retry = true;
|
||||
if (0LLU == request->current_chunk_size)
|
||||
{
|
||||
request->remaining_upload_size = 0;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no chunked encoding, give all to the client */
|
||||
if ( (0 != request->remaining_upload_size) &&
|
||||
(MHD_SIZE_UNKNOWN != request->remaining_upload_size) &&
|
||||
(request->remaining_upload_size < available) )
|
||||
{
|
||||
to_be_processed = (size_t) request->remaining_upload_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* 1. no chunked encoding, give all to the client
|
||||
* 2. client may send large chunked data, but only a smaller part is available at one time.
|
||||
*/
|
||||
to_be_processed = available;
|
||||
}
|
||||
}
|
||||
left_unprocessed = to_be_processed;
|
||||
#if FIXME_OLD_STYLE
|
||||
if (MHD_NO ==
|
||||
daemon->rc (daemon->rc_cls,
|
||||
request,
|
||||
request->url,
|
||||
request->method,
|
||||
request->version,
|
||||
buffer_head,
|
||||
&left_unprocessed,
|
||||
&request->client_context))
|
||||
{
|
||||
/* serious internal error, close connection */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_APPLICATION_CALLBACK_FAILURE_CLOSED,
|
||||
_ (
|
||||
"Application reported internal error, closing connection.\n"));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (left_unprocessed > to_be_processed)
|
||||
mhd_panic (mhd_panic_cls,
|
||||
__FILE__,
|
||||
__LINE__
|
||||
#ifdef HAVE_MESSAGES
|
||||
, _ ("libmicrohttpd API violation")
|
||||
#else
|
||||
, NULL
|
||||
#endif
|
||||
);
|
||||
if (0 != left_unprocessed)
|
||||
{
|
||||
instant_retry = false; /* client did not process everything */
|
||||
#ifdef HAVE_MESSAGES
|
||||
/* client did not process all upload data, complain if
|
||||
the setup was incorrect, which may prevent us from
|
||||
handling the rest of the request */
|
||||
if ( (MHD_TM_EXTERNAL_EVENT_LOOP == daemon->threading_mode) &&
|
||||
(! connection->suspended) )
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_APPLICATION_HUNG_CONNECTION,
|
||||
_ (
|
||||
"WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
|
||||
#endif
|
||||
}
|
||||
processed_size = to_be_processed - left_unprocessed;
|
||||
if (request->have_chunked_upload)
|
||||
request->current_chunk_offset += processed_size;
|
||||
/* dh left "processed" bytes in buffer for next time... */
|
||||
buffer_head += processed_size;
|
||||
available -= processed_size;
|
||||
if (MHD_SIZE_UNKNOWN != request->remaining_upload_size)
|
||||
request->remaining_upload_size -= processed_size;
|
||||
}
|
||||
while (instant_retry);
|
||||
if (available > 0)
|
||||
memmove (request->read_buffer,
|
||||
@@ -2796,58 +2824,59 @@ cleanup_connection (struct MHD_Connection *connection)
|
||||
return; /* Prevent double cleanup. */
|
||||
connection->request.in_cleanup = true;
|
||||
if (NULL != connection->request.response)
|
||||
{
|
||||
MHD_response_queue_for_destroy (connection->request.response);
|
||||
connection->request.response = NULL;
|
||||
}
|
||||
{
|
||||
MHD_response_queue_for_destroy (connection->request.response);
|
||||
connection->request.response = NULL;
|
||||
}
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
if (connection->suspended)
|
||||
{
|
||||
DLL_remove (daemon->suspended_connections_head,
|
||||
daemon->suspended_connections_tail,
|
||||
connection);
|
||||
connection->suspended = false;
|
||||
}
|
||||
{
|
||||
DLL_remove (daemon->suspended_connections_head,
|
||||
daemon->suspended_connections_tail,
|
||||
connection);
|
||||
connection->suspended = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
|
||||
{
|
||||
if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
|
||||
{
|
||||
if (connection->connection_timeout ==
|
||||
daemon->connection_default_timeout)
|
||||
XDLL_remove (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
else
|
||||
XDLL_remove (daemon->manual_timeout_head,
|
||||
daemon->manual_timeout_tail,
|
||||
connection);
|
||||
}
|
||||
DLL_remove (daemon->connections_head,
|
||||
daemon->connections_tail,
|
||||
connection);
|
||||
if (connection->connection_timeout ==
|
||||
daemon->connection_default_timeout)
|
||||
XDLL_remove (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
else
|
||||
XDLL_remove (daemon->manual_timeout_head,
|
||||
daemon->manual_timeout_tail,
|
||||
connection);
|
||||
}
|
||||
DLL_remove (daemon->connections_head,
|
||||
daemon->connections_tail,
|
||||
connection);
|
||||
}
|
||||
DLL_insert (daemon->cleanup_head,
|
||||
daemon->cleanup_tail,
|
||||
connection);
|
||||
daemon->cleanup_tail,
|
||||
connection);
|
||||
connection->resuming = false;
|
||||
connection->request.in_idle = false;
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
|
||||
{
|
||||
/* if we were at the connection limit before and are in
|
||||
thread-per-connection mode, signal the main thread
|
||||
to resume accepting connections */
|
||||
if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
|
||||
(! MHD_itc_activate_ (daemon->itc,
|
||||
"c")) )
|
||||
{
|
||||
/* if we were at the connection limit before and are in
|
||||
thread-per-connection mode, signal the main thread
|
||||
to resume accepting connections */
|
||||
if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
|
||||
(! MHD_itc_activate_ (daemon->itc,
|
||||
"c")) )
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ITC_USE_FAILED,
|
||||
_("Failed to signal end of connection via inter-thread communication channel"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ITC_USE_FAILED,
|
||||
_ (
|
||||
"Failed to signal end of connection via inter-thread communication channel"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2870,31 +2899,31 @@ connection_epoll_update_ (struct MHD_Connection *connection)
|
||||
(0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
|
||||
( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->request.event_loop_info) &&
|
||||
(0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) ||
|
||||
( (MHD_EVENT_LOOP_INFO_READ == connection->request.event_loop_info) &&
|
||||
(0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
|
||||
{
|
||||
/* add to epoll set */
|
||||
struct epoll_event event;
|
||||
( (MHD_EVENT_LOOP_INFO_READ == connection->request.event_loop_info) &&
|
||||
(0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
|
||||
{
|
||||
/* add to epoll set */
|
||||
struct epoll_event event;
|
||||
|
||||
event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
|
||||
event.data.ptr = connection;
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_ADD,
|
||||
connection->socket_fd,
|
||||
&event))
|
||||
{
|
||||
event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
|
||||
event.data.ptr = connection;
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_ADD,
|
||||
connection->socket_fd,
|
||||
&event))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_ADD_FAILED,
|
||||
_("Call to epoll_ctl failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_ADD_FAILED,
|
||||
_ ("Call to epoll_ctl failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
connection->request.state = MHD_REQUEST_CLOSED;
|
||||
cleanup_connection (connection);
|
||||
return false;
|
||||
}
|
||||
connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
|
||||
connection->request.state = MHD_REQUEST_CLOSED;
|
||||
cleanup_connection (connection);
|
||||
return false;
|
||||
}
|
||||
connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -2922,142 +2951,142 @@ connection_update_event_loop_info (struct MHD_Connection *connection)
|
||||
struct MHD_TLS_Plugin *tls;
|
||||
|
||||
if ( (NULL != (tls = daemon->tls_api)) &&
|
||||
(tls->update_event_loop_info (tls->cls,
|
||||
connection->tls_cs,
|
||||
&request->event_loop_info)) )
|
||||
(tls->update_event_loop_info (tls->cls,
|
||||
connection->tls_cs,
|
||||
&request->event_loop_info)) )
|
||||
return; /* TLS has decided what to do */
|
||||
}
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
while (1)
|
||||
{
|
||||
{
|
||||
#if DEBUG_STATES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_STATE_MACHINE_STATUS_REPORT,
|
||||
_("In function %s handling connection at state: %s\n"),
|
||||
__FUNCTION__,
|
||||
MHD_state_to_string (request->state));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_STATE_MACHINE_STATUS_REPORT,
|
||||
_ ("In function %s handling connection at state: %s\n"),
|
||||
__FUNCTION__,
|
||||
MHD_state_to_string (request->state));
|
||||
#endif
|
||||
switch (request->state)
|
||||
{
|
||||
case MHD_REQUEST_INIT:
|
||||
case MHD_REQUEST_URL_RECEIVED:
|
||||
case MHD_REQUEST_HEADER_PART_RECEIVED:
|
||||
/* while reading headers, we always grow the
|
||||
read buffer if needed, no size-check required */
|
||||
if ( (request->read_buffer_offset == request->read_buffer_size) &&
|
||||
(! try_grow_read_buffer (request)) )
|
||||
{
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CLIENT_HEADER_TOO_BIG,
|
||||
(NULL != request->url)
|
||||
? MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
|
||||
: MHD_HTTP_URI_TOO_LONG,
|
||||
REQUEST_TOO_BIG);
|
||||
continue;
|
||||
}
|
||||
if (! connection->read_closed)
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
|
||||
else
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
|
||||
break;
|
||||
case MHD_REQUEST_HEADERS_RECEIVED:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
case MHD_REQUEST_HEADERS_PROCESSED:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
case MHD_REQUEST_CONTINUE_SENDING:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_REQUEST_CONTINUE_SENT:
|
||||
if (request->read_buffer_offset == request->read_buffer_size)
|
||||
{
|
||||
if ( (! try_grow_read_buffer (request)) &&
|
||||
(MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode) )
|
||||
{
|
||||
/* failed to grow the read buffer, and the client
|
||||
which is supposed to handle the received data in
|
||||
a *blocking* fashion (in this mode) did not
|
||||
handle the data as it was supposed to!
|
||||
|
||||
=> we would either have to do busy-waiting
|
||||
(on the client, which would likely fail),
|
||||
or if we do nothing, we would just timeout
|
||||
on the connection (if a timeout is even set!).
|
||||
|
||||
Solution: we kill the connection with an error */
|
||||
transmit_error_response (request,
|
||||
MHD_SC_APPLICATION_HUNG_CONNECTION_CLOSED,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
INTERNAL_ERROR);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ( (request->read_buffer_offset < request->read_buffer_size) &&
|
||||
(! connection->read_closed) )
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
|
||||
else
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
|
||||
break;
|
||||
case MHD_REQUEST_BODY_RECEIVED:
|
||||
case MHD_REQUEST_FOOTER_PART_RECEIVED:
|
||||
/* while reading footers, we always grow the
|
||||
read buffer if needed, no size-check required */
|
||||
if (connection->read_closed)
|
||||
{
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_READ_FAIL_CLOSED,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
|
||||
/* transition to FOOTERS_RECEIVED
|
||||
happens in read handler */
|
||||
break;
|
||||
case MHD_REQUEST_FOOTERS_RECEIVED:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
|
||||
break;
|
||||
case MHD_REQUEST_HEADERS_SENDING:
|
||||
/* headers in buffer, keep writing */
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_REQUEST_HEADERS_SENT:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
case MHD_REQUEST_NORMAL_BODY_READY:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_REQUEST_NORMAL_BODY_UNREADY:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
|
||||
break;
|
||||
case MHD_REQUEST_CHUNKED_BODY_READY:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_REQUEST_CHUNKED_BODY_UNREADY:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
|
||||
break;
|
||||
case MHD_REQUEST_BODY_SENT:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
case MHD_REQUEST_FOOTERS_SENDING:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_REQUEST_FOOTERS_SENT:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
case MHD_REQUEST_CLOSED:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
|
||||
return; /* do nothing, not even reading */
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
case MHD_REQUEST_UPGRADE:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
default:
|
||||
mhd_assert (0);
|
||||
}
|
||||
switch (request->state)
|
||||
{
|
||||
case MHD_REQUEST_INIT:
|
||||
case MHD_REQUEST_URL_RECEIVED:
|
||||
case MHD_REQUEST_HEADER_PART_RECEIVED:
|
||||
/* while reading headers, we always grow the
|
||||
read buffer if needed, no size-check required */
|
||||
if ( (request->read_buffer_offset == request->read_buffer_size) &&
|
||||
(! try_grow_read_buffer (request)) )
|
||||
{
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CLIENT_HEADER_TOO_BIG,
|
||||
(NULL != request->url)
|
||||
? MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
|
||||
: MHD_HTTP_URI_TOO_LONG,
|
||||
REQUEST_TOO_BIG);
|
||||
continue;
|
||||
}
|
||||
if (! connection->read_closed)
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
|
||||
else
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
|
||||
break;
|
||||
case MHD_REQUEST_HEADERS_RECEIVED:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
case MHD_REQUEST_HEADERS_PROCESSED:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
case MHD_REQUEST_CONTINUE_SENDING:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_REQUEST_CONTINUE_SENT:
|
||||
if (request->read_buffer_offset == request->read_buffer_size)
|
||||
{
|
||||
if ( (! try_grow_read_buffer (request)) &&
|
||||
(MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode) )
|
||||
{
|
||||
/* failed to grow the read buffer, and the client
|
||||
which is supposed to handle the received data in
|
||||
a *blocking* fashion (in this mode) did not
|
||||
handle the data as it was supposed to!
|
||||
|
||||
=> we would either have to do busy-waiting
|
||||
(on the client, which would likely fail),
|
||||
or if we do nothing, we would just timeout
|
||||
on the connection (if a timeout is even set!).
|
||||
|
||||
Solution: we kill the connection with an error */
|
||||
transmit_error_response (request,
|
||||
MHD_SC_APPLICATION_HUNG_CONNECTION_CLOSED,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
INTERNAL_ERROR);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ( (request->read_buffer_offset < request->read_buffer_size) &&
|
||||
(! connection->read_closed) )
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
|
||||
else
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
|
||||
break;
|
||||
case MHD_REQUEST_BODY_RECEIVED:
|
||||
case MHD_REQUEST_FOOTER_PART_RECEIVED:
|
||||
/* while reading footers, we always grow the
|
||||
read buffer if needed, no size-check required */
|
||||
if (connection->read_closed)
|
||||
{
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_READ_FAIL_CLOSED,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
|
||||
/* transition to FOOTERS_RECEIVED
|
||||
happens in read handler */
|
||||
break;
|
||||
case MHD_REQUEST_FOOTERS_RECEIVED:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
|
||||
break;
|
||||
case MHD_REQUEST_HEADERS_SENDING:
|
||||
/* headers in buffer, keep writing */
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_REQUEST_HEADERS_SENT:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
case MHD_REQUEST_NORMAL_BODY_READY:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_REQUEST_NORMAL_BODY_UNREADY:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
|
||||
break;
|
||||
case MHD_REQUEST_CHUNKED_BODY_READY:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_REQUEST_CHUNKED_BODY_UNREADY:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
|
||||
break;
|
||||
case MHD_REQUEST_BODY_SENT:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
case MHD_REQUEST_FOOTERS_SENDING:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_REQUEST_FOOTERS_SENT:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
case MHD_REQUEST_CLOSED:
|
||||
request->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
|
||||
return; /* do nothing, not even reading */
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
case MHD_REQUEST_UPGRADE:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
default:
|
||||
mhd_assert (0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3082,491 +3111,494 @@ MHD_request_handle_idle_ (struct MHD_Request *request)
|
||||
|
||||
request->in_idle = true;
|
||||
while (! connection->suspended)
|
||||
{
|
||||
{
|
||||
#ifdef HTTPS_SUPPORT
|
||||
struct MHD_TLS_Plugin *tls;
|
||||
struct MHD_TLS_Plugin *tls;
|
||||
|
||||
if ( (NULL != (tls = daemon->tls_api)) &&
|
||||
(! tls->idle_ready (tls->cls,
|
||||
connection->tls_cs)) )
|
||||
break;
|
||||
if ( (NULL != (tls = daemon->tls_api)) &&
|
||||
(! tls->idle_ready (tls->cls,
|
||||
connection->tls_cs)) )
|
||||
break;
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
#if DEBUG_STATES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_STATE_MACHINE_STATUS_REPORT,
|
||||
_("In function %s handling connection at state: %s\n"),
|
||||
__FUNCTION__,
|
||||
MHD_state_to_string (request->state));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_STATE_MACHINE_STATUS_REPORT,
|
||||
_ ("In function %s handling connection at state: %s\n"),
|
||||
__FUNCTION__,
|
||||
MHD_state_to_string (request->state));
|
||||
#endif
|
||||
switch (request->state)
|
||||
switch (request->state)
|
||||
{
|
||||
case MHD_REQUEST_INIT:
|
||||
line = get_next_header_line (request,
|
||||
&line_len);
|
||||
/* Check for empty string, as we might want
|
||||
to tolerate 'spurious' empty lines; also
|
||||
NULL means we didn't get a full line yet;
|
||||
line is not 0-terminated here. */
|
||||
if ( (NULL == line) ||
|
||||
(0 == line[0]) )
|
||||
{
|
||||
if (MHD_REQUEST_INIT != request->state)
|
||||
continue;
|
||||
if (connection->read_closed)
|
||||
{
|
||||
case MHD_REQUEST_INIT:
|
||||
line = get_next_header_line (request,
|
||||
&line_len);
|
||||
/* Check for empty string, as we might want
|
||||
to tolerate 'spurious' empty lines; also
|
||||
NULL means we didn't get a full line yet;
|
||||
line is not 0-terminated here. */
|
||||
if ( (NULL == line) ||
|
||||
(0 == line[0]) )
|
||||
{
|
||||
if (MHD_REQUEST_INIT != request->state)
|
||||
continue;
|
||||
if (connection->read_closed)
|
||||
{
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_READ_FAIL_CLOSED,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (MHD_NO ==
|
||||
parse_initial_message_line (request,
|
||||
line,
|
||||
line_len))
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_CLOSED,
|
||||
NULL);
|
||||
else
|
||||
request->state = MHD_REQUEST_URL_RECEIVED;
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_READ_FAIL_CLOSED,
|
||||
NULL);
|
||||
continue;
|
||||
case MHD_REQUEST_URL_RECEIVED:
|
||||
line = get_next_header_line (request,
|
||||
NULL);
|
||||
if (NULL == line)
|
||||
{
|
||||
if (MHD_REQUEST_URL_RECEIVED != request->state)
|
||||
continue;
|
||||
if (connection->read_closed)
|
||||
{
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_READ_FAIL_CLOSED,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (0 == line[0])
|
||||
{
|
||||
request->state = MHD_REQUEST_HEADERS_RECEIVED;
|
||||
request->header_size = (size_t) (line - request->read_buffer);
|
||||
continue;
|
||||
}
|
||||
if (! process_header_line (request,
|
||||
line))
|
||||
{
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
REQUEST_MALFORMED);
|
||||
break;
|
||||
}
|
||||
request->state = MHD_REQUEST_HEADER_PART_RECEIVED;
|
||||
continue;
|
||||
case MHD_REQUEST_HEADER_PART_RECEIVED:
|
||||
line = get_next_header_line (request,
|
||||
NULL);
|
||||
if (NULL == line)
|
||||
{
|
||||
if (request->state != MHD_REQUEST_HEADER_PART_RECEIVED)
|
||||
continue;
|
||||
if (connection->read_closed)
|
||||
{
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_READ_FAIL_CLOSED,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (MHD_NO ==
|
||||
process_broken_line (request,
|
||||
line,
|
||||
MHD_HEADER_KIND))
|
||||
continue;
|
||||
if (0 == line[0])
|
||||
{
|
||||
request->state = MHD_REQUEST_HEADERS_RECEIVED;
|
||||
request->header_size = (size_t) (line - request->read_buffer);
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
case MHD_REQUEST_HEADERS_RECEIVED:
|
||||
parse_request_headers (request);
|
||||
if (MHD_REQUEST_CLOSED == request->state)
|
||||
continue;
|
||||
request->state = MHD_REQUEST_HEADERS_PROCESSED;
|
||||
if (connection->suspended)
|
||||
break;
|
||||
continue;
|
||||
case MHD_REQUEST_HEADERS_PROCESSED:
|
||||
call_request_handler (request); /* first call */
|
||||
if (MHD_REQUEST_CLOSED == request->state)
|
||||
continue;
|
||||
if (need_100_continue (request))
|
||||
{
|
||||
request->state = MHD_REQUEST_CONTINUE_SENDING;
|
||||
if (socket_flush_possible (connection))
|
||||
socket_start_extra_buffering (connection);
|
||||
else
|
||||
socket_start_no_buffering (connection);
|
||||
break;
|
||||
}
|
||||
if ( (NULL != request->response) &&
|
||||
( (MHD_METHOD_POST == request->method) ||
|
||||
(MHD_METHOD_PUT == request->method) ) )
|
||||
{
|
||||
/* we refused (no upload allowed!) */
|
||||
request->remaining_upload_size = 0;
|
||||
/* force close, in case client still tries to upload... */
|
||||
connection->read_closed = true;
|
||||
}
|
||||
request->state = (0 == request->remaining_upload_size)
|
||||
? MHD_REQUEST_FOOTERS_RECEIVED
|
||||
: MHD_REQUEST_CONTINUE_SENT;
|
||||
if (connection->suspended)
|
||||
break;
|
||||
continue;
|
||||
case MHD_REQUEST_CONTINUE_SENDING:
|
||||
if (request->continue_message_write_offset ==
|
||||
MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE))
|
||||
{
|
||||
request->state = MHD_REQUEST_CONTINUE_SENT;
|
||||
if (! socket_flush_possible (connection))
|
||||
socket_start_no_buffering_flush (connection);
|
||||
else
|
||||
socket_start_normal_buffering (connection);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case MHD_REQUEST_CONTINUE_SENT:
|
||||
if (0 != request->read_buffer_offset)
|
||||
{
|
||||
process_request_body (request); /* loop call */
|
||||
if (MHD_REQUEST_CLOSED == request->state)
|
||||
continue;
|
||||
}
|
||||
if ( (0 == request->remaining_upload_size) ||
|
||||
( (MHD_SIZE_UNKNOWN == request->remaining_upload_size) &&
|
||||
(0 == request->read_buffer_offset) &&
|
||||
(connection->read_closed) ) )
|
||||
{
|
||||
if ( (request->have_chunked_upload) &&
|
||||
(! connection->read_closed) )
|
||||
request->state = MHD_REQUEST_BODY_RECEIVED;
|
||||
else
|
||||
request->state = MHD_REQUEST_FOOTERS_RECEIVED;
|
||||
if (connection->suspended)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case MHD_REQUEST_BODY_RECEIVED:
|
||||
line = get_next_header_line (request,
|
||||
NULL);
|
||||
if (NULL == line)
|
||||
{
|
||||
if (request->state != MHD_REQUEST_BODY_RECEIVED)
|
||||
continue;
|
||||
if (connection->read_closed)
|
||||
{
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_CLOSED,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (0 == line[0])
|
||||
{
|
||||
request->state = MHD_REQUEST_FOOTERS_RECEIVED;
|
||||
if (connection->suspended)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if (MHD_NO == process_header_line (request,
|
||||
line))
|
||||
{
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
REQUEST_MALFORMED);
|
||||
break;
|
||||
}
|
||||
request->state = MHD_REQUEST_FOOTER_PART_RECEIVED;
|
||||
continue;
|
||||
case MHD_REQUEST_FOOTER_PART_RECEIVED:
|
||||
line = get_next_header_line (request,
|
||||
NULL);
|
||||
if (NULL == line)
|
||||
{
|
||||
if (request->state != MHD_REQUEST_FOOTER_PART_RECEIVED)
|
||||
continue;
|
||||
if (connection->read_closed)
|
||||
{
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_CLOSED,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (MHD_NO ==
|
||||
process_broken_line (request,
|
||||
line,
|
||||
MHD_FOOTER_KIND))
|
||||
continue;
|
||||
if (0 == line[0])
|
||||
{
|
||||
request->state = MHD_REQUEST_FOOTERS_RECEIVED;
|
||||
if (connection->suspended)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
case MHD_REQUEST_FOOTERS_RECEIVED:
|
||||
call_request_handler (request); /* "final" call */
|
||||
if (request->state == MHD_REQUEST_CLOSED)
|
||||
continue;
|
||||
if (NULL == request->response)
|
||||
break; /* try again next time */
|
||||
if (! build_header_response (request))
|
||||
{
|
||||
/* oops - close! */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_FAILED_RESPONSE_HEADER_GENERATION,
|
||||
_("Closing connection (failed to create response header)\n"));
|
||||
continue;
|
||||
}
|
||||
request->state = MHD_REQUEST_HEADERS_SENDING;
|
||||
if (MHD_NO != socket_flush_possible (connection))
|
||||
socket_start_extra_buffering (connection);
|
||||
else
|
||||
socket_start_no_buffering (connection);
|
||||
|
||||
break;
|
||||
case MHD_REQUEST_HEADERS_SENDING:
|
||||
/* no default action */
|
||||
break;
|
||||
case MHD_REQUEST_HEADERS_SENT:
|
||||
/* Some clients may take some actions right after header receive */
|
||||
if (MHD_NO != socket_flush_possible (connection))
|
||||
socket_start_no_buffering_flush (connection);
|
||||
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
if (NULL != request->response->upgrade_handler)
|
||||
{
|
||||
socket_start_normal_buffering (connection);
|
||||
request->state = MHD_REQUEST_UPGRADE;
|
||||
#if FIXME_LEGACY_STYLE
|
||||
/* This request is "upgraded". Pass socket to application. */
|
||||
if (! MHD_response_execute_upgrade_ (request->response,
|
||||
request))
|
||||
{
|
||||
/* upgrade failed, fail hard */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_CLOSED,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* Response is not required anymore for this request. */
|
||||
{
|
||||
struct MHD_Response * const resp = request->response;
|
||||
|
||||
request->response = NULL;
|
||||
MHD_response_queue_for_destroy (resp);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
if (MHD_NO != socket_flush_possible (connection))
|
||||
socket_start_extra_buffering (connection);
|
||||
else
|
||||
socket_start_normal_buffering (connection);
|
||||
|
||||
if (request->have_chunked_upload)
|
||||
request->state = MHD_REQUEST_CHUNKED_BODY_UNREADY;
|
||||
else
|
||||
request->state = MHD_REQUEST_NORMAL_BODY_UNREADY;
|
||||
continue;
|
||||
case MHD_REQUEST_NORMAL_BODY_READY:
|
||||
/* nothing to do here */
|
||||
break;
|
||||
case MHD_REQUEST_NORMAL_BODY_UNREADY:
|
||||
if (NULL != request->response->crc)
|
||||
MHD_mutex_lock_chk_ (&request->response->mutex);
|
||||
if (0 == request->response->total_size)
|
||||
{
|
||||
if (NULL != request->response->crc)
|
||||
MHD_mutex_unlock_chk_ (&request->response->mutex);
|
||||
request->state = MHD_REQUEST_BODY_SENT;
|
||||
continue;
|
||||
}
|
||||
if (try_ready_normal_body (request))
|
||||
{
|
||||
if (NULL != request->response->crc)
|
||||
MHD_mutex_unlock_chk_ (&request->response->mutex);
|
||||
request->state = MHD_REQUEST_NORMAL_BODY_READY;
|
||||
/* Buffering for flushable socket was already enabled*/
|
||||
if (MHD_NO == socket_flush_possible (connection))
|
||||
socket_start_no_buffering (connection);
|
||||
break;
|
||||
}
|
||||
/* mutex was already unlocked by "try_ready_normal_body */
|
||||
/* not ready, no socket action */
|
||||
break;
|
||||
case MHD_REQUEST_CHUNKED_BODY_READY:
|
||||
/* nothing to do here */
|
||||
break;
|
||||
case MHD_REQUEST_CHUNKED_BODY_UNREADY:
|
||||
if (NULL != request->response->crc)
|
||||
MHD_mutex_lock_chk_ (&request->response->mutex);
|
||||
if ( (0 == request->response->total_size) ||
|
||||
(request->response_write_position ==
|
||||
request->response->total_size) )
|
||||
{
|
||||
if (NULL != request->response->crc)
|
||||
MHD_mutex_unlock_chk_ (&request->response->mutex);
|
||||
request->state = MHD_REQUEST_BODY_SENT;
|
||||
continue;
|
||||
}
|
||||
if (try_ready_chunked_body (request))
|
||||
{
|
||||
if (NULL != request->response->crc)
|
||||
MHD_mutex_unlock_chk_ (&request->response->mutex);
|
||||
request->state = MHD_REQUEST_CHUNKED_BODY_READY;
|
||||
/* Buffering for flushable socket was already enabled */
|
||||
if (MHD_NO == socket_flush_possible (connection))
|
||||
socket_start_no_buffering (connection);
|
||||
continue;
|
||||
}
|
||||
/* mutex was already unlocked by try_ready_chunked_body */
|
||||
break;
|
||||
case MHD_REQUEST_BODY_SENT:
|
||||
if (! build_header_response (request))
|
||||
{
|
||||
/* oops - close! */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_FAILED_RESPONSE_HEADER_GENERATION,
|
||||
_("Closing connection (failed to create response header)\n"));
|
||||
continue;
|
||||
}
|
||||
if ( (! request->have_chunked_upload) ||
|
||||
(request->write_buffer_send_offset ==
|
||||
request->write_buffer_append_offset) )
|
||||
request->state = MHD_REQUEST_FOOTERS_SENT;
|
||||
else
|
||||
request->state = MHD_REQUEST_FOOTERS_SENDING;
|
||||
continue;
|
||||
case MHD_REQUEST_FOOTERS_SENDING:
|
||||
/* no default action */
|
||||
break;
|
||||
case MHD_REQUEST_FOOTERS_SENT:
|
||||
{
|
||||
struct MHD_Response *response = request->response;
|
||||
|
||||
if (MHD_HTTP_PROCESSING == response->status_code)
|
||||
{
|
||||
/* After this type of response, we allow sending another! */
|
||||
request->state = MHD_REQUEST_HEADERS_PROCESSED;
|
||||
MHD_response_queue_for_destroy (response);
|
||||
request->response = NULL;
|
||||
/* FIXME: maybe partially reset memory pool? */
|
||||
continue;
|
||||
}
|
||||
if (socket_flush_possible (connection))
|
||||
socket_start_no_buffering_flush (connection);
|
||||
else
|
||||
socket_start_normal_buffering (connection);
|
||||
|
||||
if (NULL != response->termination_cb)
|
||||
{
|
||||
response->termination_cb (response->termination_cb_cls,
|
||||
MHD_REQUEST_TERMINATED_COMPLETED_OK,
|
||||
request->client_context);
|
||||
}
|
||||
MHD_response_queue_for_destroy (response);
|
||||
request->response = NULL;
|
||||
}
|
||||
if ( (MHD_CONN_USE_KEEPALIVE != request->keepalive) ||
|
||||
(connection->read_closed) )
|
||||
{
|
||||
/* have to close for some reason */
|
||||
MHD_connection_close_ (connection,
|
||||
MHD_REQUEST_TERMINATED_COMPLETED_OK);
|
||||
MHD_pool_destroy (connection->pool);
|
||||
connection->pool = NULL;
|
||||
request->read_buffer = NULL;
|
||||
request->read_buffer_size = 0;
|
||||
request->read_buffer_offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* can try to keep-alive */
|
||||
if (socket_flush_possible (connection))
|
||||
socket_start_normal_buffering (connection);
|
||||
request->version_s = NULL;
|
||||
request->state = MHD_REQUEST_INIT;
|
||||
request->last = NULL;
|
||||
request->colon = NULL;
|
||||
request->header_size = 0;
|
||||
request->keepalive = MHD_CONN_KEEPALIVE_UNKOWN;
|
||||
/* Reset the read buffer to the starting size,
|
||||
preserving the bytes we have already read. */
|
||||
request->read_buffer
|
||||
= MHD_pool_reset (connection->pool,
|
||||
request->read_buffer,
|
||||
request->read_buffer_offset,
|
||||
daemon->connection_memory_limit_b / 2);
|
||||
request->read_buffer_size
|
||||
= daemon->connection_memory_limit_b / 2;
|
||||
}
|
||||
// FIXME: this is too much, NULLs out some of the things
|
||||
// initialized above...
|
||||
memset (request,
|
||||
0,
|
||||
sizeof (struct MHD_Request));
|
||||
request->daemon = daemon;
|
||||
request->connection = connection;
|
||||
continue;
|
||||
case MHD_REQUEST_CLOSED:
|
||||
cleanup_connection (connection);
|
||||
request->in_idle = false;
|
||||
return false;
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
case MHD_REQUEST_UPGRADE:
|
||||
request->in_idle = false;
|
||||
return true; /* keep open */
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
default:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (MHD_NO ==
|
||||
parse_initial_message_line (request,
|
||||
line,
|
||||
line_len))
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_CLOSED,
|
||||
NULL);
|
||||
else
|
||||
request->state = MHD_REQUEST_URL_RECEIVED;
|
||||
continue;
|
||||
case MHD_REQUEST_URL_RECEIVED:
|
||||
line = get_next_header_line (request,
|
||||
NULL);
|
||||
if (NULL == line)
|
||||
{
|
||||
if (MHD_REQUEST_URL_RECEIVED != request->state)
|
||||
continue;
|
||||
if (connection->read_closed)
|
||||
{
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_READ_FAIL_CLOSED,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (0 == line[0])
|
||||
{
|
||||
request->state = MHD_REQUEST_HEADERS_RECEIVED;
|
||||
request->header_size = (size_t) (line - request->read_buffer);
|
||||
continue;
|
||||
}
|
||||
if (! process_header_line (request,
|
||||
line))
|
||||
{
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
REQUEST_MALFORMED);
|
||||
break;
|
||||
}
|
||||
request->state = MHD_REQUEST_HEADER_PART_RECEIVED;
|
||||
continue;
|
||||
case MHD_REQUEST_HEADER_PART_RECEIVED:
|
||||
line = get_next_header_line (request,
|
||||
NULL);
|
||||
if (NULL == line)
|
||||
{
|
||||
if (request->state != MHD_REQUEST_HEADER_PART_RECEIVED)
|
||||
continue;
|
||||
if (connection->read_closed)
|
||||
{
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_READ_FAIL_CLOSED,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (MHD_NO ==
|
||||
process_broken_line (request,
|
||||
line,
|
||||
MHD_HEADER_KIND))
|
||||
continue;
|
||||
if (0 == line[0])
|
||||
{
|
||||
request->state = MHD_REQUEST_HEADERS_RECEIVED;
|
||||
request->header_size = (size_t) (line - request->read_buffer);
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
case MHD_REQUEST_HEADERS_RECEIVED:
|
||||
parse_request_headers (request);
|
||||
if (MHD_REQUEST_CLOSED == request->state)
|
||||
continue;
|
||||
request->state = MHD_REQUEST_HEADERS_PROCESSED;
|
||||
if (connection->suspended)
|
||||
break;
|
||||
continue;
|
||||
case MHD_REQUEST_HEADERS_PROCESSED:
|
||||
call_request_handler (request); /* first call */
|
||||
if (MHD_REQUEST_CLOSED == request->state)
|
||||
continue;
|
||||
if (need_100_continue (request))
|
||||
{
|
||||
request->state = MHD_REQUEST_CONTINUE_SENDING;
|
||||
if (socket_flush_possible (connection))
|
||||
socket_start_extra_buffering (connection);
|
||||
else
|
||||
socket_start_no_buffering (connection);
|
||||
break;
|
||||
}
|
||||
if ( (NULL != request->response) &&
|
||||
( (MHD_METHOD_POST == request->method) ||
|
||||
(MHD_METHOD_PUT == request->method) ) )
|
||||
{
|
||||
/* we refused (no upload allowed!) */
|
||||
request->remaining_upload_size = 0;
|
||||
/* force close, in case client still tries to upload... */
|
||||
connection->read_closed = true;
|
||||
}
|
||||
request->state = (0 == request->remaining_upload_size)
|
||||
? MHD_REQUEST_FOOTERS_RECEIVED
|
||||
: MHD_REQUEST_CONTINUE_SENT;
|
||||
if (connection->suspended)
|
||||
break;
|
||||
continue;
|
||||
case MHD_REQUEST_CONTINUE_SENDING:
|
||||
if (request->continue_message_write_offset ==
|
||||
MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE))
|
||||
{
|
||||
request->state = MHD_REQUEST_CONTINUE_SENT;
|
||||
if (! socket_flush_possible (connection))
|
||||
socket_start_no_buffering_flush (connection);
|
||||
else
|
||||
socket_start_normal_buffering (connection);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case MHD_REQUEST_CONTINUE_SENT:
|
||||
if (0 != request->read_buffer_offset)
|
||||
{
|
||||
process_request_body (request); /* loop call */
|
||||
if (MHD_REQUEST_CLOSED == request->state)
|
||||
continue;
|
||||
}
|
||||
if ( (0 == request->remaining_upload_size) ||
|
||||
( (MHD_SIZE_UNKNOWN == request->remaining_upload_size) &&
|
||||
(0 == request->read_buffer_offset) &&
|
||||
(connection->read_closed) ) )
|
||||
{
|
||||
if ( (request->have_chunked_upload) &&
|
||||
(! connection->read_closed) )
|
||||
request->state = MHD_REQUEST_BODY_RECEIVED;
|
||||
else
|
||||
request->state = MHD_REQUEST_FOOTERS_RECEIVED;
|
||||
if (connection->suspended)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case MHD_REQUEST_BODY_RECEIVED:
|
||||
line = get_next_header_line (request,
|
||||
NULL);
|
||||
if (NULL == line)
|
||||
{
|
||||
if (request->state != MHD_REQUEST_BODY_RECEIVED)
|
||||
continue;
|
||||
if (connection->read_closed)
|
||||
{
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_CLOSED,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (0 == line[0])
|
||||
{
|
||||
request->state = MHD_REQUEST_FOOTERS_RECEIVED;
|
||||
if (connection->suspended)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if (MHD_NO == process_header_line (request,
|
||||
line))
|
||||
{
|
||||
transmit_error_response (request,
|
||||
MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
REQUEST_MALFORMED);
|
||||
break;
|
||||
}
|
||||
request->state = MHD_REQUEST_FOOTER_PART_RECEIVED;
|
||||
continue;
|
||||
case MHD_REQUEST_FOOTER_PART_RECEIVED:
|
||||
line = get_next_header_line (request,
|
||||
NULL);
|
||||
if (NULL == line)
|
||||
{
|
||||
if (request->state != MHD_REQUEST_FOOTER_PART_RECEIVED)
|
||||
continue;
|
||||
if (connection->read_closed)
|
||||
{
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_CLOSED,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (MHD_NO ==
|
||||
process_broken_line (request,
|
||||
line,
|
||||
MHD_FOOTER_KIND))
|
||||
continue;
|
||||
if (0 == line[0])
|
||||
{
|
||||
request->state = MHD_REQUEST_FOOTERS_RECEIVED;
|
||||
if (connection->suspended)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
case MHD_REQUEST_FOOTERS_RECEIVED:
|
||||
call_request_handler (request); /* "final" call */
|
||||
if (request->state == MHD_REQUEST_CLOSED)
|
||||
continue;
|
||||
if (NULL == request->response)
|
||||
break; /* try again next time */
|
||||
if (! build_header_response (request))
|
||||
{
|
||||
/* oops - close! */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_FAILED_RESPONSE_HEADER_GENERATION,
|
||||
_ (
|
||||
"Closing connection (failed to create response header)\n"));
|
||||
continue;
|
||||
}
|
||||
request->state = MHD_REQUEST_HEADERS_SENDING;
|
||||
if (MHD_NO != socket_flush_possible (connection))
|
||||
socket_start_extra_buffering (connection);
|
||||
else
|
||||
socket_start_no_buffering (connection);
|
||||
|
||||
break;
|
||||
case MHD_REQUEST_HEADERS_SENDING:
|
||||
/* no default action */
|
||||
break;
|
||||
case MHD_REQUEST_HEADERS_SENT:
|
||||
/* Some clients may take some actions right after header receive */
|
||||
if (MHD_NO != socket_flush_possible (connection))
|
||||
socket_start_no_buffering_flush (connection);
|
||||
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
if (NULL != request->response->upgrade_handler)
|
||||
{
|
||||
socket_start_normal_buffering (connection);
|
||||
request->state = MHD_REQUEST_UPGRADE;
|
||||
#if FIXME_LEGACY_STYLE
|
||||
/* This request is "upgraded". Pass socket to application. */
|
||||
if (! MHD_response_execute_upgrade_ (request->response,
|
||||
request))
|
||||
{
|
||||
/* upgrade failed, fail hard */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_CONNECTION_CLOSED,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* Response is not required anymore for this request. */
|
||||
{
|
||||
struct MHD_Response *const resp = request->response;
|
||||
|
||||
request->response = NULL;
|
||||
MHD_response_queue_for_destroy (resp);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
if (MHD_NO != socket_flush_possible (connection))
|
||||
socket_start_extra_buffering (connection);
|
||||
else
|
||||
socket_start_normal_buffering (connection);
|
||||
|
||||
if (request->have_chunked_upload)
|
||||
request->state = MHD_REQUEST_CHUNKED_BODY_UNREADY;
|
||||
else
|
||||
request->state = MHD_REQUEST_NORMAL_BODY_UNREADY;
|
||||
continue;
|
||||
case MHD_REQUEST_NORMAL_BODY_READY:
|
||||
/* nothing to do here */
|
||||
break;
|
||||
case MHD_REQUEST_NORMAL_BODY_UNREADY:
|
||||
if (NULL != request->response->crc)
|
||||
MHD_mutex_lock_chk_ (&request->response->mutex);
|
||||
if (0 == request->response->total_size)
|
||||
{
|
||||
if (NULL != request->response->crc)
|
||||
MHD_mutex_unlock_chk_ (&request->response->mutex);
|
||||
request->state = MHD_REQUEST_BODY_SENT;
|
||||
continue;
|
||||
}
|
||||
if (try_ready_normal_body (request))
|
||||
{
|
||||
if (NULL != request->response->crc)
|
||||
MHD_mutex_unlock_chk_ (&request->response->mutex);
|
||||
request->state = MHD_REQUEST_NORMAL_BODY_READY;
|
||||
/* Buffering for flushable socket was already enabled*/
|
||||
if (MHD_NO == socket_flush_possible (connection))
|
||||
socket_start_no_buffering (connection);
|
||||
break;
|
||||
}
|
||||
/* mutex was already unlocked by "try_ready_normal_body */
|
||||
/* not ready, no socket action */
|
||||
break;
|
||||
case MHD_REQUEST_CHUNKED_BODY_READY:
|
||||
/* nothing to do here */
|
||||
break;
|
||||
case MHD_REQUEST_CHUNKED_BODY_UNREADY:
|
||||
if (NULL != request->response->crc)
|
||||
MHD_mutex_lock_chk_ (&request->response->mutex);
|
||||
if ( (0 == request->response->total_size) ||
|
||||
(request->response_write_position ==
|
||||
request->response->total_size) )
|
||||
{
|
||||
if (NULL != request->response->crc)
|
||||
MHD_mutex_unlock_chk_ (&request->response->mutex);
|
||||
request->state = MHD_REQUEST_BODY_SENT;
|
||||
continue;
|
||||
}
|
||||
if (try_ready_chunked_body (request))
|
||||
{
|
||||
if (NULL != request->response->crc)
|
||||
MHD_mutex_unlock_chk_ (&request->response->mutex);
|
||||
request->state = MHD_REQUEST_CHUNKED_BODY_READY;
|
||||
/* Buffering for flushable socket was already enabled */
|
||||
if (MHD_NO == socket_flush_possible (connection))
|
||||
socket_start_no_buffering (connection);
|
||||
continue;
|
||||
}
|
||||
/* mutex was already unlocked by try_ready_chunked_body */
|
||||
break;
|
||||
case MHD_REQUEST_BODY_SENT:
|
||||
if (! build_header_response (request))
|
||||
{
|
||||
/* oops - close! */
|
||||
CONNECTION_CLOSE_ERROR (connection,
|
||||
MHD_SC_FAILED_RESPONSE_HEADER_GENERATION,
|
||||
_ (
|
||||
"Closing connection (failed to create response header)\n"));
|
||||
continue;
|
||||
}
|
||||
if ( (! request->have_chunked_upload) ||
|
||||
(request->write_buffer_send_offset ==
|
||||
request->write_buffer_append_offset) )
|
||||
request->state = MHD_REQUEST_FOOTERS_SENT;
|
||||
else
|
||||
request->state = MHD_REQUEST_FOOTERS_SENDING;
|
||||
continue;
|
||||
case MHD_REQUEST_FOOTERS_SENDING:
|
||||
/* no default action */
|
||||
break;
|
||||
case MHD_REQUEST_FOOTERS_SENT:
|
||||
{
|
||||
struct MHD_Response *response = request->response;
|
||||
|
||||
if (MHD_HTTP_PROCESSING == response->status_code)
|
||||
{
|
||||
/* After this type of response, we allow sending another! */
|
||||
request->state = MHD_REQUEST_HEADERS_PROCESSED;
|
||||
MHD_response_queue_for_destroy (response);
|
||||
request->response = NULL;
|
||||
/* FIXME: maybe partially reset memory pool? */
|
||||
continue;
|
||||
}
|
||||
if (socket_flush_possible (connection))
|
||||
socket_start_no_buffering_flush (connection);
|
||||
else
|
||||
socket_start_normal_buffering (connection);
|
||||
|
||||
if (NULL != response->termination_cb)
|
||||
{
|
||||
response->termination_cb (response->termination_cb_cls,
|
||||
MHD_REQUEST_TERMINATED_COMPLETED_OK,
|
||||
request->client_context);
|
||||
}
|
||||
MHD_response_queue_for_destroy (response);
|
||||
request->response = NULL;
|
||||
}
|
||||
if ( (MHD_CONN_USE_KEEPALIVE != request->keepalive) ||
|
||||
(connection->read_closed) )
|
||||
{
|
||||
/* have to close for some reason */
|
||||
MHD_connection_close_ (connection,
|
||||
MHD_REQUEST_TERMINATED_COMPLETED_OK);
|
||||
MHD_pool_destroy (connection->pool);
|
||||
connection->pool = NULL;
|
||||
request->read_buffer = NULL;
|
||||
request->read_buffer_size = 0;
|
||||
request->read_buffer_offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* can try to keep-alive */
|
||||
if (socket_flush_possible (connection))
|
||||
socket_start_normal_buffering (connection);
|
||||
request->version_s = NULL;
|
||||
request->state = MHD_REQUEST_INIT;
|
||||
request->last = NULL;
|
||||
request->colon = NULL;
|
||||
request->header_size = 0;
|
||||
request->keepalive = MHD_CONN_KEEPALIVE_UNKOWN;
|
||||
/* Reset the read buffer to the starting size,
|
||||
preserving the bytes we have already read. */
|
||||
request->read_buffer
|
||||
= MHD_pool_reset (connection->pool,
|
||||
request->read_buffer,
|
||||
request->read_buffer_offset,
|
||||
daemon->connection_memory_limit_b / 2);
|
||||
request->read_buffer_size
|
||||
= daemon->connection_memory_limit_b / 2;
|
||||
}
|
||||
// FIXME: this is too much, NULLs out some of the things
|
||||
// initialized above...
|
||||
memset (request,
|
||||
0,
|
||||
sizeof (struct MHD_Request));
|
||||
request->daemon = daemon;
|
||||
request->connection = connection;
|
||||
continue;
|
||||
case MHD_REQUEST_CLOSED:
|
||||
cleanup_connection (connection);
|
||||
request->in_idle = false;
|
||||
return false;
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
case MHD_REQUEST_UPGRADE:
|
||||
request->in_idle = false;
|
||||
return true; /* keep open */
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
default:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (! connection->suspended)
|
||||
{
|
||||
time_t timeout;
|
||||
timeout = connection->connection_timeout;
|
||||
if ( (0 != timeout) &&
|
||||
(timeout < (MHD_monotonic_sec_counter ()
|
||||
- connection->last_activity)) )
|
||||
{
|
||||
time_t timeout;
|
||||
timeout = connection->connection_timeout;
|
||||
if ( (0 != timeout) &&
|
||||
(timeout < (MHD_monotonic_sec_counter() - connection->last_activity)) )
|
||||
{
|
||||
MHD_connection_close_ (connection,
|
||||
MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
|
||||
request->in_idle = false;
|
||||
return true;
|
||||
}
|
||||
MHD_connection_close_ (connection,
|
||||
MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
|
||||
request->in_idle = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
connection_update_event_loop_info (connection);
|
||||
ret = true;
|
||||
#ifdef EPOLL_SUPPORT
|
||||
if ( (! connection->suspended) &&
|
||||
(MHD_ELS_EPOLL == daemon->event_loop_syscall) )
|
||||
{
|
||||
ret = connection_epoll_update_ (connection);
|
||||
}
|
||||
{
|
||||
ret = connection_epoll_update_ (connection);
|
||||
}
|
||||
#endif /* EPOLL_SUPPORT */
|
||||
request->in_idle = false;
|
||||
return ret;
|
||||
@@ -3589,9 +3621,9 @@ MHD_request_handle_idle_ (struct MHD_Request *request)
|
||||
// FIXME: rename connection->request?
|
||||
int
|
||||
MHD_connection_call_handlers_ (struct MHD_Connection *con,
|
||||
bool read_ready,
|
||||
bool write_ready,
|
||||
bool force_close)
|
||||
bool read_ready,
|
||||
bool write_ready,
|
||||
bool force_close)
|
||||
{
|
||||
struct MHD_Daemon *daemon = con->daemon;
|
||||
int ret;
|
||||
@@ -3604,38 +3636,38 @@ MHD_connection_call_handlers_ (struct MHD_Connection *con,
|
||||
read_ready = true;
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
if (! force_close)
|
||||
{
|
||||
if ( (MHD_EVENT_LOOP_INFO_READ ==
|
||||
con->request.event_loop_info) &&
|
||||
read_ready)
|
||||
{
|
||||
if ( (MHD_EVENT_LOOP_INFO_READ ==
|
||||
con->request.event_loop_info) &&
|
||||
read_ready)
|
||||
{
|
||||
MHD_request_handle_read_ (&con->request);
|
||||
ret = MHD_request_handle_idle_ (&con->request);
|
||||
states_info_processed = true;
|
||||
}
|
||||
/* No need to check value of 'ret' here as closed connection
|
||||
* cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */
|
||||
if ( (MHD_EVENT_LOOP_INFO_WRITE ==
|
||||
con->request.event_loop_info) &&
|
||||
write_ready)
|
||||
{
|
||||
MHD_request_handle_write_ (&con->request);
|
||||
ret = MHD_request_handle_idle_ (&con->request);
|
||||
states_info_processed = true;
|
||||
}
|
||||
MHD_request_handle_read_ (&con->request);
|
||||
ret = MHD_request_handle_idle_ (&con->request);
|
||||
states_info_processed = true;
|
||||
}
|
||||
/* No need to check value of 'ret' here as closed connection
|
||||
* cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */
|
||||
if ( (MHD_EVENT_LOOP_INFO_WRITE ==
|
||||
con->request.event_loop_info) &&
|
||||
write_ready)
|
||||
{
|
||||
MHD_request_handle_write_ (&con->request);
|
||||
ret = MHD_request_handle_idle_ (&con->request);
|
||||
states_info_processed = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MHD_connection_close_ (con,
|
||||
MHD_REQUEST_TERMINATED_WITH_ERROR);
|
||||
return MHD_request_handle_idle_ (&con->request);
|
||||
}
|
||||
{
|
||||
MHD_connection_close_ (con,
|
||||
MHD_REQUEST_TERMINATED_WITH_ERROR);
|
||||
return MHD_request_handle_idle_ (&con->request);
|
||||
}
|
||||
|
||||
if (! states_info_processed)
|
||||
{ /* Connection is not read or write ready, but external conditions
|
||||
{ /* Connection is not read or write ready, but external conditions
|
||||
* may be changed and need to be processed. */
|
||||
ret = MHD_request_handle_idle_ (&con->request);
|
||||
}
|
||||
ret = MHD_request_handle_idle_ (&con->request);
|
||||
}
|
||||
/* Fast track for fast connections. */
|
||||
/* If full request was read by single read_handler() invocation
|
||||
and headers were completely prepared by single MHD_request_handle_idle_()
|
||||
@@ -3647,24 +3679,24 @@ MHD_connection_call_handlers_ (struct MHD_Connection *con,
|
||||
/* No need to check 'ret' as connection is always in
|
||||
* MHD_CONNECTION_CLOSED state if 'ret' is equal 'MHD_NO'. */
|
||||
else if (on_fasttrack &&
|
||||
con->sk_nonblck)
|
||||
con->sk_nonblck)
|
||||
{
|
||||
if (MHD_REQUEST_HEADERS_SENDING == con->request.state)
|
||||
{
|
||||
if (MHD_REQUEST_HEADERS_SENDING == con->request.state)
|
||||
{
|
||||
MHD_request_handle_write_ (&con->request);
|
||||
/* Always call 'MHD_request_handle_idle_()' after each read/write. */
|
||||
ret = MHD_request_handle_idle_ (&con->request);
|
||||
}
|
||||
/* If all headers were sent by single write_handler() and
|
||||
* response body is prepared by single MHD_request_handle_idle_()
|
||||
* call - continue. */
|
||||
if ((MHD_REQUEST_NORMAL_BODY_READY == con->request.state) ||
|
||||
(MHD_REQUEST_CHUNKED_BODY_READY == con->request.state))
|
||||
{
|
||||
MHD_request_handle_write_ (&con->request);
|
||||
ret = MHD_request_handle_idle_ (&con->request);
|
||||
}
|
||||
MHD_request_handle_write_ (&con->request);
|
||||
/* Always call 'MHD_request_handle_idle_()' after each read/write. */
|
||||
ret = MHD_request_handle_idle_ (&con->request);
|
||||
}
|
||||
/* If all headers were sent by single write_handler() and
|
||||
* response body is prepared by single MHD_request_handle_idle_()
|
||||
* call - continue. */
|
||||
if ((MHD_REQUEST_NORMAL_BODY_READY == con->request.state) ||
|
||||
(MHD_REQUEST_CHUNKED_BODY_READY == con->request.state))
|
||||
{
|
||||
MHD_request_handle_write_ (&con->request);
|
||||
ret = MHD_request_handle_idle_ (&con->request);
|
||||
}
|
||||
}
|
||||
|
||||
/* All connection's data and states are processed for this turn.
|
||||
* If connection already has more data to be processed - use
|
||||
@@ -3676,17 +3708,17 @@ MHD_connection_call_handlers_ (struct MHD_Connection *con,
|
||||
* without space in read buffer will be market as 'info block'. */
|
||||
if ( (! daemon->data_already_pending) &&
|
||||
(MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode) )
|
||||
{
|
||||
if (MHD_EVENT_LOOP_INFO_BLOCK ==
|
||||
con->request.event_loop_info)
|
||||
daemon->data_already_pending = true;
|
||||
{
|
||||
if (MHD_EVENT_LOOP_INFO_BLOCK ==
|
||||
con->request.event_loop_info)
|
||||
daemon->data_already_pending = true;
|
||||
#ifdef HTTPS_SUPPORT
|
||||
else if ( (con->tls_read_ready) &&
|
||||
(MHD_EVENT_LOOP_INFO_READ ==
|
||||
con->request.event_loop_info) )
|
||||
daemon->data_already_pending = true;
|
||||
else if ( (con->tls_read_ready) &&
|
||||
(MHD_EVENT_LOOP_INFO_READ ==
|
||||
con->request.event_loop_info) )
|
||||
daemon->data_already_pending = true;
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,10 +40,10 @@
|
||||
*/
|
||||
int
|
||||
MHD_connection_call_handlers_ (struct MHD_Connection *con,
|
||||
bool read_ready,
|
||||
bool write_ready,
|
||||
bool force_close)
|
||||
MHD_NONNULL (1);
|
||||
bool read_ready,
|
||||
bool write_ready,
|
||||
bool force_close)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -58,7 +58,7 @@ MHD_connection_call_handlers_ (struct MHD_Connection *con,
|
||||
*/
|
||||
bool
|
||||
MHD_request_handle_idle_ (struct MHD_Request *request)
|
||||
MHD_NONNULL (1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -49,7 +49,7 @@ connection_cleanup_upgraded (struct MHD_Connection *connection)
|
||||
|
||||
if (NULL != (tls = connection->daemon->tls_api))
|
||||
(void) tls->shutdown_connection (tls->cls,
|
||||
connection->tls_cs);
|
||||
connection->tls_cs);
|
||||
}
|
||||
if (MHD_INVALID_SOCKET != urh->mhd.socket)
|
||||
MHD_socket_close_chk_ (urh->mhd.socket);
|
||||
@@ -65,7 +65,7 @@ connection_cleanup_upgraded (struct MHD_Connection *connection)
|
||||
/**
|
||||
* Free resources associated with all closed connections. (destroy
|
||||
* responses, free buffers, etc.). All closed connections are kept in
|
||||
* the "cleanup" doubly-linked list.
|
||||
* the "cleanup" doubly-linked list.
|
||||
*
|
||||
* @remark To be called only from thread that process daemon's
|
||||
* select()/poll()/etc.
|
||||
@@ -79,79 +79,79 @@ MHD_connection_cleanup_ (struct MHD_Daemon *daemon)
|
||||
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
while (NULL != (pos = daemon->cleanup_tail))
|
||||
{
|
||||
DLL_remove (daemon->cleanup_head,
|
||||
daemon->cleanup_tail,
|
||||
pos);
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
{
|
||||
DLL_remove (daemon->cleanup_head,
|
||||
daemon->cleanup_tail,
|
||||
pos);
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
|
||||
if ( (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) &&
|
||||
(! pos->thread_joined) &&
|
||||
(! MHD_join_thread_ (pos->pid.handle)) )
|
||||
MHD_PANIC (_("Failed to join a thread\n"));
|
||||
if ( (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) &&
|
||||
(! pos->thread_joined) &&
|
||||
(! MHD_join_thread_ (pos->pid.handle)) )
|
||||
MHD_PANIC (_ ("Failed to join a thread\n"));
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
connection_cleanup_upgraded (pos);
|
||||
connection_cleanup_upgraded (pos);
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
MHD_pool_destroy (pos->pool);
|
||||
MHD_pool_destroy (pos->pool);
|
||||
#ifdef HTTPS_SUPPORT
|
||||
{
|
||||
struct MHD_TLS_Plugin *tls;
|
||||
|
||||
if (NULL != (tls = daemon->tls_api))
|
||||
tls->teardown_connection (tls->cls,
|
||||
pos->tls_cs);
|
||||
}
|
||||
{
|
||||
struct MHD_TLS_Plugin *tls;
|
||||
|
||||
if (NULL != (tls = daemon->tls_api))
|
||||
tls->teardown_connection (tls->cls,
|
||||
pos->tls_cs);
|
||||
}
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
|
||||
/* clean up the connection */
|
||||
if (NULL != daemon->notify_connection_cb)
|
||||
daemon->notify_connection_cb (daemon->notify_connection_cb_cls,
|
||||
pos,
|
||||
MHD_CONNECTION_NOTIFY_CLOSED);
|
||||
MHD_ip_limit_del (daemon,
|
||||
(const struct sockaddr *) &pos->addr,
|
||||
pos->addr_len);
|
||||
/* clean up the connection */
|
||||
if (NULL != daemon->notify_connection_cb)
|
||||
daemon->notify_connection_cb (daemon->notify_connection_cb_cls,
|
||||
pos,
|
||||
MHD_CONNECTION_NOTIFY_CLOSED);
|
||||
MHD_ip_limit_del (daemon,
|
||||
(const struct sockaddr *) &pos->addr,
|
||||
pos->addr_len);
|
||||
#ifdef EPOLL_SUPPORT
|
||||
if (MHD_ELS_EPOLL == daemon->event_loop_syscall)
|
||||
{
|
||||
if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
|
||||
{
|
||||
EDLL_remove (daemon->eready_head,
|
||||
daemon->eready_tail,
|
||||
pos);
|
||||
pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
|
||||
}
|
||||
if ( (-1 != daemon->epoll_fd) &&
|
||||
(0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
|
||||
{
|
||||
/* epoll documentation suggests that closing a FD
|
||||
automatically removes it from the epoll set; however,
|
||||
this is not true as if we fail to do manually remove it,
|
||||
we are still seeing an event for this fd in epoll,
|
||||
causing grief (use-after-free...) --- at least on my
|
||||
system. */
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_DEL,
|
||||
pos->socket_fd,
|
||||
NULL))
|
||||
MHD_PANIC (_("Failed to remove FD from epoll set\n"));
|
||||
pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (NULL != pos->request.response)
|
||||
{
|
||||
MHD_response_queue_for_destroy (pos->request.response);
|
||||
pos->request.response = NULL;
|
||||
}
|
||||
if (MHD_INVALID_SOCKET != pos->socket_fd)
|
||||
MHD_socket_close_chk_ (pos->socket_fd);
|
||||
free (pos);
|
||||
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
daemon->connections--;
|
||||
daemon->at_limit = false;
|
||||
if (MHD_ELS_EPOLL == daemon->event_loop_syscall)
|
||||
{
|
||||
if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
|
||||
{
|
||||
EDLL_remove (daemon->eready_head,
|
||||
daemon->eready_tail,
|
||||
pos);
|
||||
pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
|
||||
}
|
||||
if ( (-1 != daemon->epoll_fd) &&
|
||||
(0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
|
||||
{
|
||||
/* epoll documentation suggests that closing a FD
|
||||
automatically removes it from the epoll set; however,
|
||||
this is not true as if we fail to do manually remove it,
|
||||
we are still seeing an event for this fd in epoll,
|
||||
causing grief (use-after-free...) --- at least on my
|
||||
system. */
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_DEL,
|
||||
pos->socket_fd,
|
||||
NULL))
|
||||
MHD_PANIC (_ ("Failed to remove FD from epoll set\n"));
|
||||
pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (NULL != pos->request.response)
|
||||
{
|
||||
MHD_response_queue_for_destroy (pos->request.response);
|
||||
pos->request.response = NULL;
|
||||
}
|
||||
if (MHD_INVALID_SOCKET != pos->socket_fd)
|
||||
MHD_socket_close_chk_ (pos->socket_fd);
|
||||
free (pos);
|
||||
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
daemon->connections--;
|
||||
daemon->at_limit = false;
|
||||
}
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
/**
|
||||
* @file lib/connection_cleanup.h
|
||||
* @brief functions to cleanup completed connection
|
||||
* @brief functions to cleanup completed connection
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#ifndef CONNECTION_CLEANUP_H
|
||||
@@ -28,7 +28,7 @@
|
||||
/**
|
||||
* Free resources associated with all closed connections. (destroy
|
||||
* responses, free buffers, etc.). All closed connections are kept in
|
||||
* the "cleanup" doubly-linked list.
|
||||
* the "cleanup" doubly-linked list.
|
||||
*
|
||||
* @remark To be called only from thread that process daemon's
|
||||
* select()/poll()/etc.
|
||||
@@ -37,6 +37,6 @@
|
||||
*/
|
||||
void
|
||||
MHD_connection_cleanup_ (struct MHD_Daemon *daemon)
|
||||
MHD_NONNULL (1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
#endif
|
||||
|
||||
+30
-30
@@ -40,33 +40,33 @@ MHD_connection_mark_closed_ (struct MHD_Connection *connection)
|
||||
connection->request.state = MHD_REQUEST_CLOSED;
|
||||
connection->request.event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
|
||||
if (! daemon->enable_turbo)
|
||||
{
|
||||
{
|
||||
#ifdef HTTPS_SUPPORT
|
||||
struct MHD_TLS_Plugin *tls;
|
||||
struct MHD_TLS_Plugin *tls;
|
||||
|
||||
/* For TLS connection use shutdown of TLS layer
|
||||
* and do not shutdown TCP socket. This give more
|
||||
* chances to send TLS closure data to remote side.
|
||||
* Closure of TLS layer will be interpreted by
|
||||
* remote side as end of transmission. */
|
||||
if (NULL != (tls = daemon->tls_api))
|
||||
{
|
||||
if (MHD_YES !=
|
||||
tls->shutdown_connection (tls->cls,
|
||||
connection->tls_cs))
|
||||
{
|
||||
(void) shutdown (connection->socket_fd,
|
||||
SHUT_WR);
|
||||
/* FIXME: log errors */
|
||||
}
|
||||
}
|
||||
else /* Combined with next 'shutdown()'. */
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
{
|
||||
(void) shutdown (connection->socket_fd,
|
||||
SHUT_WR); /* FIXME: log errors */
|
||||
}
|
||||
/* For TLS connection use shutdown of TLS layer
|
||||
* and do not shutdown TCP socket. This give more
|
||||
* chances to send TLS closure data to remote side.
|
||||
* Closure of TLS layer will be interpreted by
|
||||
* remote side as end of transmission. */
|
||||
if (NULL != (tls = daemon->tls_api))
|
||||
{
|
||||
if (MHD_YES !=
|
||||
tls->shutdown_connection (tls->cls,
|
||||
connection->tls_cs))
|
||||
{
|
||||
(void) shutdown (connection->socket_fd,
|
||||
SHUT_WR);
|
||||
/* FIXME: log errors */
|
||||
}
|
||||
}
|
||||
else /* Combined with next 'shutdown()'. */
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
{
|
||||
(void) shutdown (connection->socket_fd,
|
||||
SHUT_WR); /* FIXME: log errors */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,14 +90,14 @@ MHD_connection_close_ (struct MHD_Connection *connection,
|
||||
(void) rtc; // FIXME
|
||||
MHD_connection_mark_closed_ (connection);
|
||||
if (NULL != resp)
|
||||
{
|
||||
connection->request.response = NULL;
|
||||
MHD_response_queue_for_destroy (resp);
|
||||
}
|
||||
{
|
||||
connection->request.response = NULL;
|
||||
MHD_response_queue_for_destroy (resp);
|
||||
}
|
||||
if (NULL != daemon->notify_connection_cb)
|
||||
daemon->notify_connection_cb (daemon->notify_connection_cb_cls,
|
||||
connection,
|
||||
MHD_CONNECTION_NOTIFY_CLOSED);
|
||||
connection,
|
||||
MHD_CONNECTION_NOTIFY_CLOSED);
|
||||
}
|
||||
|
||||
/* end of connection_close.c */
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
*/
|
||||
void
|
||||
MHD_connection_mark_closed_ (struct MHD_Connection *connection)
|
||||
MHD_NONNULL (1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -51,6 +51,6 @@ MHD_connection_mark_closed_ (struct MHD_Connection *connection)
|
||||
void
|
||||
MHD_connection_close_ (struct MHD_Connection *connection,
|
||||
enum MHD_RequestTerminationCode rtc)
|
||||
MHD_NONNULL (1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -55,34 +55,34 @@ MHD_connection_finish_forward_ (struct MHD_Connection *connection)
|
||||
EPOLL_CTL_DEL,
|
||||
connection->socket_fd,
|
||||
NULL)) )
|
||||
{
|
||||
MHD_PANIC (_("Failed to remove FD from epoll set\n"));
|
||||
}
|
||||
{
|
||||
MHD_PANIC (_ ("Failed to remove FD from epoll set\n"));
|
||||
}
|
||||
if (urh->in_eready_list)
|
||||
{
|
||||
EDLL_remove (daemon->eready_urh_head,
|
||||
daemon->eready_urh_tail,
|
||||
urh);
|
||||
urh->in_eready_list = false;
|
||||
}
|
||||
{
|
||||
EDLL_remove (daemon->eready_urh_head,
|
||||
daemon->eready_urh_tail,
|
||||
urh);
|
||||
urh->in_eready_list = false;
|
||||
}
|
||||
#endif /* EPOLL_SUPPORT */
|
||||
if (MHD_INVALID_SOCKET != urh->mhd.socket)
|
||||
{
|
||||
{
|
||||
#if EPOLL_SUPPORT
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
|
||||
(0 != epoll_ctl (daemon->epoll_upgrade_fd,
|
||||
EPOLL_CTL_DEL,
|
||||
urh->mhd.socket,
|
||||
NULL)) )
|
||||
{
|
||||
MHD_PANIC (_("Failed to remove FD from epoll set\n"));
|
||||
}
|
||||
#endif /* EPOLL_SUPPORT */
|
||||
/* Reflect remote disconnect to application by breaking
|
||||
* socketpair connection. */
|
||||
shutdown (urh->mhd.socket,
|
||||
SHUT_RDWR);
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
|
||||
(0 != epoll_ctl (daemon->epoll_upgrade_fd,
|
||||
EPOLL_CTL_DEL,
|
||||
urh->mhd.socket,
|
||||
NULL)) )
|
||||
{
|
||||
MHD_PANIC (_ ("Failed to remove FD from epoll set\n"));
|
||||
}
|
||||
#endif /* EPOLL_SUPPORT */
|
||||
/* Reflect remote disconnect to application by breaking
|
||||
* socketpair connection. */
|
||||
shutdown (urh->mhd.socket,
|
||||
SHUT_RDWR);
|
||||
}
|
||||
/* Socketpair sockets will remain open as they will be
|
||||
* used with MHD_UPGRADE_ACTION_CLOSE. They will be
|
||||
* closed by MHD_cleanup_upgraded_connection_() during
|
||||
|
||||
@@ -39,6 +39,6 @@
|
||||
*/
|
||||
void
|
||||
MHD_connection_finish_forward_ (struct MHD_Connection *connection)
|
||||
MHD_NONNULL (1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -42,13 +42,13 @@
|
||||
*/
|
||||
enum MHD_Bool
|
||||
MHD_connection_get_information_sz (struct MHD_Connection *connection,
|
||||
enum MHD_ConnectionInformationType info_type,
|
||||
union MHD_ConnectionInformation *return_value,
|
||||
size_t return_value_size)
|
||||
enum MHD_ConnectionInformationType info_type,
|
||||
union MHD_ConnectionInformation *return_value,
|
||||
size_t return_value_size)
|
||||
{
|
||||
#define CHECK_SIZE(type) if (sizeof(type) < return_value_size) \
|
||||
return MHD_NO
|
||||
|
||||
|
||||
switch (info_type)
|
||||
{
|
||||
#ifdef HTTPS_SUPPORT
|
||||
@@ -63,7 +63,7 @@ MHD_connection_get_information_sz (struct MHD_Connection *connection,
|
||||
CHECK_SIZE (int);
|
||||
if (NULL == connection->tls_cs)
|
||||
return MHD_NO;
|
||||
//return_value->protocol
|
||||
// return_value->protocol
|
||||
// = gnutls_protocol_get_version (connection->tls_session);
|
||||
return MHD_NO; // FIXME: to be implemented
|
||||
case MHD_CONNECTION_INFORMATION_GNUTLS_SESSION:
|
||||
@@ -103,7 +103,7 @@ MHD_connection_get_information_sz (struct MHD_Connection *connection,
|
||||
default:
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
|
||||
#undef CHECK_SIZE
|
||||
}
|
||||
|
||||
|
||||
@@ -35,44 +35,44 @@
|
||||
*/
|
||||
void
|
||||
MHD_connection_set_timeout (struct MHD_Connection *connection,
|
||||
unsigned int timeout_s)
|
||||
unsigned int timeout_s)
|
||||
{
|
||||
struct MHD_Daemon *daemon = connection->daemon;
|
||||
|
||||
connection->last_activity = MHD_monotonic_sec_counter();
|
||||
|
||||
connection->last_activity = MHD_monotonic_sec_counter ();
|
||||
if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
|
||||
{
|
||||
/* Simple case, no need to lock to update DLLs */
|
||||
connection->connection_timeout = (time_t) timeout_s;
|
||||
return;
|
||||
}
|
||||
{
|
||||
/* Simple case, no need to lock to update DLLs */
|
||||
connection->connection_timeout = (time_t) timeout_s;
|
||||
return;
|
||||
}
|
||||
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
if (! connection->suspended)
|
||||
{
|
||||
if (connection->connection_timeout ==
|
||||
daemon->connection_default_timeout)
|
||||
XDLL_remove (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
else
|
||||
XDLL_remove (daemon->manual_timeout_head,
|
||||
daemon->manual_timeout_tail,
|
||||
connection);
|
||||
}
|
||||
{
|
||||
if (connection->connection_timeout ==
|
||||
daemon->connection_default_timeout)
|
||||
XDLL_remove (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
else
|
||||
XDLL_remove (daemon->manual_timeout_head,
|
||||
daemon->manual_timeout_tail,
|
||||
connection);
|
||||
}
|
||||
connection->connection_timeout = (time_t) timeout_s;
|
||||
if (! connection->suspended)
|
||||
{
|
||||
if (connection->connection_timeout ==
|
||||
daemon->connection_default_timeout)
|
||||
XDLL_insert (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
else
|
||||
XDLL_insert (daemon->manual_timeout_head,
|
||||
daemon->manual_timeout_tail,
|
||||
connection);
|
||||
}
|
||||
{
|
||||
if (connection->connection_timeout ==
|
||||
daemon->connection_default_timeout)
|
||||
XDLL_insert (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
else
|
||||
XDLL_insert (daemon->manual_timeout_head,
|
||||
daemon->manual_timeout_tail,
|
||||
connection);
|
||||
}
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ MHD_update_last_activity_ (struct MHD_Connection *connection)
|
||||
if (connection->suspended)
|
||||
return; /* no activity on suspended connections */
|
||||
|
||||
connection->last_activity = MHD_monotonic_sec_counter();
|
||||
connection->last_activity = MHD_monotonic_sec_counter ();
|
||||
if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
|
||||
return; /* each connection has personal timeout */
|
||||
|
||||
@@ -106,11 +106,11 @@ MHD_update_last_activity_ (struct MHD_Connection *connection)
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
/* move connection to head of timeout list (by remove + add operation) */
|
||||
XDLL_remove (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
XDLL_insert (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ MHD_connection_update_last_activity_ (struct MHD_Connection *connection)
|
||||
if (connection->suspended)
|
||||
return; /* no activity on suspended connections */
|
||||
|
||||
connection->last_activity = MHD_monotonic_sec_counter();
|
||||
connection->last_activity = MHD_monotonic_sec_counter ();
|
||||
if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
|
||||
return; /* each connection has personal timeout */
|
||||
|
||||
@@ -53,13 +53,12 @@ MHD_connection_update_last_activity_ (struct MHD_Connection *connection)
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
/* move connection to head of timeout list (by remove + add operation) */
|
||||
XDLL_remove (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
XDLL_insert (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
daemon->normal_timeout_tail,
|
||||
connection);
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
}
|
||||
|
||||
/* end of connection_update_last_activity.c */
|
||||
|
||||
|
||||
@@ -35,6 +35,6 @@
|
||||
*/
|
||||
void
|
||||
MHD_connection_update_last_activity_ (struct MHD_Connection *connection)
|
||||
MHD_NONNULL (1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -45,10 +45,10 @@ close_connection (struct MHD_Connection *pos)
|
||||
struct MHD_Daemon *daemon = pos->daemon;
|
||||
|
||||
if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
|
||||
{
|
||||
MHD_connection_mark_closed_ (pos);
|
||||
return; /* must let thread to do the rest */
|
||||
}
|
||||
{
|
||||
MHD_connection_mark_closed_ (pos);
|
||||
return; /* must let thread to do the rest */
|
||||
}
|
||||
MHD_connection_close_ (pos,
|
||||
MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
|
||||
|
||||
@@ -59,18 +59,18 @@ close_connection (struct MHD_Connection *pos)
|
||||
if (pos->connection_timeout ==
|
||||
pos->daemon->connection_default_timeout)
|
||||
XDLL_remove (daemon->normal_timeout_head,
|
||||
daemon->normal_timeout_tail,
|
||||
pos);
|
||||
daemon->normal_timeout_tail,
|
||||
pos);
|
||||
else
|
||||
XDLL_remove (daemon->manual_timeout_head,
|
||||
daemon->manual_timeout_tail,
|
||||
pos);
|
||||
daemon->manual_timeout_tail,
|
||||
pos);
|
||||
DLL_remove (daemon->connections_head,
|
||||
daemon->connections_tail,
|
||||
pos);
|
||||
daemon->connections_tail,
|
||||
pos);
|
||||
DLL_insert (daemon->cleanup_head,
|
||||
daemon->cleanup_tail,
|
||||
pos);
|
||||
daemon->cleanup_tail,
|
||||
pos);
|
||||
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
}
|
||||
@@ -89,7 +89,8 @@ void
|
||||
MHD_daemon_close_all_connections_ (struct MHD_Daemon *daemon)
|
||||
{
|
||||
struct MHD_Connection *pos;
|
||||
const bool used_thr_p_c = (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode);
|
||||
const bool used_thr_p_c = (MHD_TM_THREAD_PER_CONNECTION ==
|
||||
daemon->threading_mode);
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
const bool upg_allowed = (! daemon->disallow_upgrade);
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
@@ -103,16 +104,16 @@ MHD_daemon_close_all_connections_ (struct MHD_Daemon *daemon)
|
||||
/* give upgraded HTTPS connections a chance to finish */
|
||||
/* 'daemon->urh_head' is not used in thread-per-connection mode. */
|
||||
for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
|
||||
{
|
||||
urhn = urh->prev;
|
||||
/* call generic forwarding function for passing data
|
||||
with chance to detect that application is done. */
|
||||
MHD_upgrade_response_handle_process_ (urh);
|
||||
MHD_connection_finish_forward_ (urh->connection);
|
||||
urh->clean_ready = true;
|
||||
/* Resuming will move connection to cleanup list. */
|
||||
MHD_request_resume (&urh->connection->request);
|
||||
}
|
||||
{
|
||||
urhn = urh->prev;
|
||||
/* call generic forwarding function for passing data
|
||||
with chance to detect that application is done. */
|
||||
MHD_upgrade_response_handle_process_ (urh);
|
||||
MHD_connection_finish_forward_ (urh->connection);
|
||||
urh->clean_ready = true;
|
||||
/* Resuming will move connection to cleanup list. */
|
||||
MHD_request_resume (&urh->connection->request);
|
||||
}
|
||||
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
|
||||
|
||||
/* Give suspended connections a chance to resume to avoid
|
||||
@@ -120,89 +121,93 @@ MHD_daemon_close_all_connections_ (struct MHD_Daemon *daemon)
|
||||
connections left in case of a tight race with a recently
|
||||
resumed connection. */
|
||||
if (! daemon->disallow_suspend_resume)
|
||||
{
|
||||
daemon->resuming = true; /* Force check for pending resume. */
|
||||
MHD_resume_suspended_connections_ (daemon);
|
||||
}
|
||||
{
|
||||
daemon->resuming = true; /* Force check for pending resume. */
|
||||
MHD_resume_suspended_connections_ (daemon);
|
||||
}
|
||||
/* first, make sure all threads are aware of shutdown; need to
|
||||
traverse DLLs in peace... */
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
if (upg_allowed)
|
||||
{
|
||||
struct MHD_Connection * susp;
|
||||
{
|
||||
struct MHD_Connection *susp;
|
||||
|
||||
susp = daemon->suspended_connections_tail;
|
||||
while (NULL != susp)
|
||||
{
|
||||
if (NULL == susp->request.urh) /* "Upgraded" connection? */
|
||||
MHD_PANIC (_("MHD_stop_daemon() called while we have suspended connections.\n"));
|
||||
susp = daemon->suspended_connections_tail;
|
||||
while (NULL != susp)
|
||||
{
|
||||
if (NULL == susp->request.urh) /* "Upgraded" connection? */
|
||||
MHD_PANIC (_ (
|
||||
"MHD_stop_daemon() called while we have suspended connections.\n"));
|
||||
#ifdef HTTPS_SUPPORT
|
||||
else if (used_tls &&
|
||||
used_thr_p_c &&
|
||||
(! susp->request.urh->clean_ready) )
|
||||
shutdown (susp->request.urh->app.socket,
|
||||
SHUT_RDWR); /* Wake thread by shutdown of app socket. */
|
||||
else if (used_tls &&
|
||||
used_thr_p_c &&
|
||||
(! susp->request.urh->clean_ready) )
|
||||
shutdown (susp->request.urh->app.socket,
|
||||
SHUT_RDWR); /* Wake thread by shutdown of app socket. */
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
else
|
||||
{
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
if (! susp->request.urh->was_closed)
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_SHUTDOWN_WITH_OPEN_UPGRADED_CONNECTION,
|
||||
_("Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
|
||||
if (! susp->request.urh->was_closed)
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_SHUTDOWN_WITH_OPEN_UPGRADED_CONNECTION,
|
||||
_ (
|
||||
"Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
|
||||
#endif
|
||||
susp->request.urh->was_closed = true;
|
||||
/* If thread-per-connection is used, connection's thread
|
||||
* may still processing "upgrade" (exiting). */
|
||||
if (! used_thr_p_c)
|
||||
MHD_connection_finish_forward_ (susp);
|
||||
/* Do not use MHD_resume_connection() as mutex is
|
||||
* already locked. */
|
||||
susp->resuming = true;
|
||||
daemon->resuming = true;
|
||||
}
|
||||
susp = susp->prev;
|
||||
}
|
||||
susp->request.urh->was_closed = true;
|
||||
/* If thread-per-connection is used, connection's thread
|
||||
* may still processing "upgrade" (exiting). */
|
||||
if (! used_thr_p_c)
|
||||
MHD_connection_finish_forward_ (susp);
|
||||
/* Do not use MHD_resume_connection() as mutex is
|
||||
* already locked. */
|
||||
susp->resuming = true;
|
||||
daemon->resuming = true;
|
||||
}
|
||||
susp = susp->prev;
|
||||
}
|
||||
}
|
||||
else /* This 'else' is combined with next 'if' */
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
if (NULL != daemon->suspended_connections_head)
|
||||
MHD_PANIC (_("MHD_stop_daemon() called while we have suspended connections.\n"));
|
||||
MHD_PANIC (_ (
|
||||
"MHD_stop_daemon() called while we have suspended connections.\n"));
|
||||
for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
|
||||
{
|
||||
shutdown (pos->socket_fd,
|
||||
SHUT_RDWR);
|
||||
{
|
||||
shutdown (pos->socket_fd,
|
||||
SHUT_RDWR);
|
||||
#if MHD_WINSOCK_SOCKETS
|
||||
if ( (used_thr_p_c) &&
|
||||
(MHD_ITC_IS_VALID_(daemon->itc)) &&
|
||||
(! MHD_itc_activate_ (daemon->itc,
|
||||
"e")) )
|
||||
MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel"));
|
||||
if ( (used_thr_p_c) &&
|
||||
(MHD_ITC_IS_VALID_ (daemon->itc)) &&
|
||||
(! MHD_itc_activate_ (daemon->itc,
|
||||
"e")) )
|
||||
MHD_PANIC (_ (
|
||||
"Failed to signal shutdown via inter-thread communication channel"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* now, collect per-connection threads */
|
||||
if (used_thr_p_c)
|
||||
{
|
||||
pos = daemon->connections_tail;
|
||||
while (NULL != pos)
|
||||
{
|
||||
pos = daemon->connections_tail;
|
||||
while (NULL != pos)
|
||||
if (! pos->thread_joined)
|
||||
{
|
||||
if (! pos->thread_joined)
|
||||
{
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
if (! MHD_join_thread_ (pos->pid.handle))
|
||||
MHD_PANIC (_("Failed to join a thread\n"));
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
pos->thread_joined = true;
|
||||
/* The thread may have concurrently modified the DLL,
|
||||
need to restart from the beginning */
|
||||
pos = daemon->connections_tail;
|
||||
continue;
|
||||
}
|
||||
pos = pos->prev;
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
if (! MHD_join_thread_ (pos->pid.handle))
|
||||
MHD_PANIC (_ ("Failed to join a thread\n"));
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
pos->thread_joined = true;
|
||||
/* The thread may have concurrently modified the DLL,
|
||||
need to restart from the beginning */
|
||||
pos = daemon->connections_tail;
|
||||
continue;
|
||||
}
|
||||
pos = pos->prev;
|
||||
}
|
||||
}
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
@@ -211,10 +216,10 @@ MHD_daemon_close_all_connections_ (struct MHD_Daemon *daemon)
|
||||
/* "Upgraded" connections that were not closed explicitly by
|
||||
* application should be moved to cleanup list too. */
|
||||
if (upg_allowed)
|
||||
{
|
||||
daemon->resuming = true; /* Force check for pending resume. */
|
||||
MHD_resume_suspended_connections_ (daemon);
|
||||
}
|
||||
{
|
||||
daemon->resuming = true; /* Force check for pending resume. */
|
||||
MHD_resume_suspended_connections_ (daemon);
|
||||
}
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
|
||||
/* now that we're alone, move everyone to cleanup */
|
||||
@@ -222,7 +227,7 @@ MHD_daemon_close_all_connections_ (struct MHD_Daemon *daemon)
|
||||
{
|
||||
if ( (used_thr_p_c) &&
|
||||
(! pos->thread_joined) )
|
||||
MHD_PANIC (_("Failed to join a thread\n"));
|
||||
MHD_PANIC (_ ("Failed to join a thread\n"));
|
||||
close_connection (pos);
|
||||
}
|
||||
MHD_connection_cleanup_ (daemon);
|
||||
|
||||
@@ -37,6 +37,6 @@
|
||||
*/
|
||||
void
|
||||
MHD_daemon_close_all_connections_ (struct MHD_Daemon *daemon)
|
||||
MHD_NONNULL (1);
|
||||
MHD_NONNULL (1);
|
||||
|
||||
#endif
|
||||
|
||||
+25
-25
@@ -38,16 +38,16 @@
|
||||
*/
|
||||
static void
|
||||
file_logger (void *cls,
|
||||
enum MHD_StatusCode sc,
|
||||
const char *fm,
|
||||
va_list ap)
|
||||
enum MHD_StatusCode sc,
|
||||
const char *fm,
|
||||
va_list ap)
|
||||
{
|
||||
FILE *f = cls;
|
||||
|
||||
(void) sc;
|
||||
(void) vfprintf (f,
|
||||
fm,
|
||||
ap);
|
||||
fm,
|
||||
ap);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,16 +84,16 @@ unescape_wrapper (void *cls,
|
||||
*/
|
||||
struct MHD_Daemon *
|
||||
MHD_daemon_create (MHD_RequestCallback cb,
|
||||
void *cb_cls)
|
||||
void *cb_cls)
|
||||
{
|
||||
struct MHD_Daemon *daemon;
|
||||
|
||||
MHD_check_global_init_();
|
||||
MHD_check_global_init_ ();
|
||||
if (NULL == (daemon = malloc (sizeof (struct MHD_Daemon))))
|
||||
return NULL;
|
||||
memset (daemon,
|
||||
0,
|
||||
sizeof (struct MHD_Daemon));
|
||||
0,
|
||||
sizeof (struct MHD_Daemon));
|
||||
#ifdef EPOLL_SUPPORT
|
||||
daemon->epoll_itc_marker = "itc_marker";
|
||||
#endif
|
||||
@@ -107,29 +107,29 @@ MHD_daemon_create (MHD_RequestCallback cb,
|
||||
#if ENABLE_DAUTH
|
||||
daemon->digest_nc_length = DIGEST_NC_LENGTH_DEFAULT;
|
||||
#endif
|
||||
daemon->listen_backlog = LISTEN_BACKLOG_DEFAULT;
|
||||
daemon->listen_backlog = LISTEN_BACKLOG_DEFAULT;
|
||||
daemon->fo_queue_length = FO_QUEUE_LENGTH_DEFAULT;
|
||||
daemon->listen_socket = MHD_INVALID_SOCKET;
|
||||
|
||||
if (! MHD_mutex_init_ (&daemon->cleanup_connection_mutex))
|
||||
{
|
||||
free (daemon);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
free (daemon);
|
||||
return NULL;
|
||||
}
|
||||
if (! MHD_mutex_init_ (&daemon->per_ip_connection_mutex))
|
||||
{
|
||||
(void) MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex);
|
||||
free (daemon);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
(void) MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex);
|
||||
free (daemon);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef DAUTH_SUPPORT
|
||||
if (! MHD_mutex_init_ (&daemon->nnc_lock))
|
||||
{
|
||||
(void) MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex);
|
||||
(void) MHD_mutex_destroy_ (&daemon->per_ip_connection_mutex);
|
||||
free (daemon);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
(void) MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex);
|
||||
(void) MHD_mutex_destroy_ (&daemon->per_ip_connection_mutex);
|
||||
free (daemon);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return daemon;
|
||||
}
|
||||
|
||||
+82
-80
@@ -46,35 +46,36 @@ stop_workers (struct MHD_Daemon *daemon)
|
||||
fd = daemon->listen_socket;
|
||||
/* Let workers shutdown in parallel. */
|
||||
for (i = 0; i < daemon->worker_pool_size; i++)
|
||||
{
|
||||
daemon->worker_pool[i].shutdown = true;
|
||||
if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
|
||||
{
|
||||
daemon->worker_pool[i].shutdown = true;
|
||||
if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
|
||||
{
|
||||
if (! MHD_itc_activate_ (daemon->worker_pool[i].itc,
|
||||
"e"))
|
||||
MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel."));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Better hope shutdown() works... */
|
||||
mhd_assert (MHD_INVALID_SOCKET != fd);
|
||||
}
|
||||
if (! MHD_itc_activate_ (daemon->worker_pool[i].itc,
|
||||
"e"))
|
||||
MHD_PANIC (_ (
|
||||
"Failed to signal shutdown via inter-thread communication channel."));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Better hope shutdown() works... */
|
||||
mhd_assert (MHD_INVALID_SOCKET != fd);
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_LISTEN_SHUTDOWN
|
||||
if (MHD_INVALID_SOCKET != fd)
|
||||
{
|
||||
(void) shutdown (fd,
|
||||
SHUT_RDWR);
|
||||
}
|
||||
{
|
||||
(void) shutdown (fd,
|
||||
SHUT_RDWR);
|
||||
}
|
||||
#endif /* HAVE_LISTEN_SHUTDOWN */
|
||||
for (i = 0; i < daemon->worker_pool_size; ++i)
|
||||
{
|
||||
MHD_daemon_destroy (&daemon->worker_pool[i]);
|
||||
}
|
||||
{
|
||||
MHD_daemon_destroy (&daemon->worker_pool[i]);
|
||||
}
|
||||
free (daemon->worker_pool);
|
||||
daemon->worker_pool = NULL;
|
||||
/* FIXME: does this still hold? */
|
||||
mhd_assert (MHD_ITC_IS_INVALID_(daemon->itc));
|
||||
mhd_assert (MHD_ITC_IS_INVALID_ (daemon->itc));
|
||||
#ifdef EPOLL_SUPPORT
|
||||
mhd_assert (-1 == daemon->epoll_fd);
|
||||
#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
|
||||
@@ -104,65 +105,66 @@ MHD_daemon_destroy (struct MHD_Daemon *daemon)
|
||||
/* FIXME: convert from here to microhttpd2-style API! */
|
||||
|
||||
if (NULL != daemon->worker_pool)
|
||||
{ /* Master daemon with worker pool. */
|
||||
stop_workers (daemon);
|
||||
}
|
||||
{ /* Master daemon with worker pool. */
|
||||
stop_workers (daemon);
|
||||
}
|
||||
else
|
||||
{
|
||||
mhd_assert (0 == daemon->worker_pool_size);
|
||||
/* Worker daemon or single-thread daemon. */
|
||||
if (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode)
|
||||
{
|
||||
mhd_assert (0 == daemon->worker_pool_size);
|
||||
/* Worker daemon or single-thread daemon. */
|
||||
if (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode)
|
||||
{
|
||||
/* Worker daemon or single daemon with internal thread(s). */
|
||||
/* Separate thread(s) is used for polling sockets. */
|
||||
if (MHD_ITC_IS_VALID_(daemon->itc))
|
||||
{
|
||||
if (! MHD_itc_activate_ (daemon->itc,
|
||||
"e"))
|
||||
MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel"));
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_LISTEN_SHUTDOWN
|
||||
if (MHD_INVALID_SOCKET != fd)
|
||||
{
|
||||
if (NULL == daemon->master)
|
||||
(void) shutdown (fd,
|
||||
SHUT_RDWR);
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_LISTEN_SHUTDOWN */
|
||||
mhd_assert (false); /* Should never happen */
|
||||
}
|
||||
|
||||
if (! MHD_join_thread_ (daemon->pid.handle))
|
||||
{
|
||||
MHD_PANIC (_("Failed to join a thread\n"));
|
||||
}
|
||||
/* close_all_connections() was called in daemon thread. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No internal threads are used for polling sockets
|
||||
(external event loop) */
|
||||
MHD_daemon_close_all_connections_ (daemon);
|
||||
}
|
||||
/* Worker daemon or single daemon with internal thread(s). */
|
||||
/* Separate thread(s) is used for polling sockets. */
|
||||
if (MHD_ITC_IS_VALID_ (daemon->itc))
|
||||
MHD_itc_destroy_chk_ (daemon->itc);
|
||||
{
|
||||
if (! MHD_itc_activate_ (daemon->itc,
|
||||
"e"))
|
||||
MHD_PANIC (_ (
|
||||
"Failed to signal shutdown via inter-thread communication channel"));
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_LISTEN_SHUTDOWN
|
||||
if (MHD_INVALID_SOCKET != fd)
|
||||
{
|
||||
if (NULL == daemon->master)
|
||||
(void) shutdown (fd,
|
||||
SHUT_RDWR);
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_LISTEN_SHUTDOWN */
|
||||
mhd_assert (false); /* Should never happen */
|
||||
}
|
||||
|
||||
if (! MHD_join_thread_ (daemon->pid.handle))
|
||||
{
|
||||
MHD_PANIC (_ ("Failed to join a thread\n"));
|
||||
}
|
||||
/* close_all_connections() was called in daemon thread. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No internal threads are used for polling sockets
|
||||
(external event loop) */
|
||||
MHD_daemon_close_all_connections_ (daemon);
|
||||
}
|
||||
if (MHD_ITC_IS_VALID_ (daemon->itc))
|
||||
MHD_itc_destroy_chk_ (daemon->itc);
|
||||
|
||||
#ifdef EPOLL_SUPPORT
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
|
||||
(-1 != daemon->epoll_fd) )
|
||||
MHD_socket_close_chk_ (daemon->epoll_fd);
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
|
||||
(-1 != daemon->epoll_fd) )
|
||||
MHD_socket_close_chk_ (daemon->epoll_fd);
|
||||
#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
|
||||
(-1 != daemon->epoll_upgrade_fd) )
|
||||
MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
|
||||
(-1 != daemon->epoll_upgrade_fd) )
|
||||
MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
|
||||
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
|
||||
#endif /* EPOLL_SUPPORT */
|
||||
|
||||
MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
|
||||
}
|
||||
MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
|
||||
}
|
||||
|
||||
if (NULL != daemon->master)
|
||||
return;
|
||||
@@ -175,18 +177,18 @@ MHD_daemon_destroy (struct MHD_Daemon *daemon)
|
||||
/* TLS clean up */
|
||||
#ifdef HTTPS_SUPPORT
|
||||
if (NULL != daemon->tls_api)
|
||||
{
|
||||
{
|
||||
#if FIXME_TLS_API
|
||||
if (daemon->have_dhparams)
|
||||
{
|
||||
gnutls_dh_params_deinit (daemon->https_mem_dhparams);
|
||||
daemon->have_dhparams = false;
|
||||
}
|
||||
gnutls_priority_deinit (daemon->priority_cache);
|
||||
if (daemon->x509_cred)
|
||||
gnutls_certificate_free_credentials (daemon->x509_cred);
|
||||
#endif
|
||||
if (daemon->have_dhparams)
|
||||
{
|
||||
gnutls_dh_params_deinit (daemon->https_mem_dhparams);
|
||||
daemon->have_dhparams = false;
|
||||
}
|
||||
gnutls_priority_deinit (daemon->priority_cache);
|
||||
if (daemon->x509_cred)
|
||||
gnutls_certificate_free_credentials (daemon->x509_cred);
|
||||
#endif
|
||||
}
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
|
||||
#ifdef DAUTH_SUPPORT
|
||||
|
||||
+273
-268
@@ -53,9 +53,9 @@
|
||||
* 'false' otherwise
|
||||
*/
|
||||
static bool
|
||||
is_urh_ready (struct MHD_UpgradeResponseHandle * const urh)
|
||||
is_urh_ready (struct MHD_UpgradeResponseHandle *const urh)
|
||||
{
|
||||
const struct MHD_Connection * const connection = urh->connection;
|
||||
const struct MHD_Connection *const connection = urh->connection;
|
||||
|
||||
if ( (0 == urh->in_buffer_size) &&
|
||||
(0 == urh->out_buffer_size) &&
|
||||
@@ -80,7 +80,7 @@ is_urh_ready (struct MHD_UpgradeResponseHandle * const urh)
|
||||
return true;
|
||||
|
||||
if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
|
||||
(urh->in_buffer_used > 0) )
|
||||
(urh->in_buffer_used > 0) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -103,99 +103,99 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon)
|
||||
{
|
||||
struct epoll_event events[MAX_EVENTS];
|
||||
int num_events;
|
||||
struct MHD_UpgradeResponseHandle * pos;
|
||||
struct MHD_UpgradeResponseHandle * prev;
|
||||
struct MHD_UpgradeResponseHandle *pos;
|
||||
struct MHD_UpgradeResponseHandle *prev;
|
||||
|
||||
num_events = MAX_EVENTS;
|
||||
while (MAX_EVENTS == num_events)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* update event masks */
|
||||
num_events = epoll_wait (daemon->epoll_upgrade_fd,
|
||||
events,
|
||||
MAX_EVENTS,
|
||||
0);
|
||||
if (-1 == num_events)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* update event masks */
|
||||
num_events = epoll_wait (daemon->epoll_upgrade_fd,
|
||||
events,
|
||||
MAX_EVENTS,
|
||||
0);
|
||||
if (-1 == num_events)
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
return MHD_SC_OK;
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
return MHD_SC_OK;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_UNEXPECTED_EPOLL_WAIT_ERROR,
|
||||
_("Call to epoll_wait failed: %s\n"),
|
||||
MHD_socket_strerr_ (err));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_UNEXPECTED_EPOLL_WAIT_ERROR,
|
||||
_ ("Call to epoll_wait failed: %s\n"),
|
||||
MHD_socket_strerr_ (err));
|
||||
#endif
|
||||
return MHD_SC_UNEXPECTED_EPOLL_WAIT_ERROR;
|
||||
}
|
||||
for (i = 0; i < (unsigned int) num_events; i++)
|
||||
{
|
||||
struct UpgradeEpollHandle * const ueh = events[i].data.ptr;
|
||||
struct MHD_UpgradeResponseHandle * const urh = ueh->urh;
|
||||
bool new_err_state = false;
|
||||
|
||||
if (urh->clean_ready)
|
||||
continue;
|
||||
|
||||
/* Update ueh state based on what is ready according to epoll() */
|
||||
if (0 != (events[i].events & EPOLLIN))
|
||||
ueh->celi |= MHD_EPOLL_STATE_READ_READY;
|
||||
if (0 != (events[i].events & EPOLLOUT))
|
||||
ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
|
||||
if (0 != (events[i].events & EPOLLHUP))
|
||||
ueh->celi |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY;
|
||||
|
||||
if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
|
||||
(0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
|
||||
{
|
||||
/* Process new error state only one time
|
||||
* and avoid continuously marking this connection
|
||||
* as 'ready'. */
|
||||
ueh->celi |= MHD_EPOLL_STATE_ERROR;
|
||||
new_err_state = true;
|
||||
}
|
||||
|
||||
if (! urh->in_eready_list)
|
||||
{
|
||||
if (new_err_state ||
|
||||
is_urh_ready(urh))
|
||||
{
|
||||
EDLL_insert (daemon->eready_urh_head,
|
||||
daemon->eready_urh_tail,
|
||||
urh);
|
||||
urh->in_eready_list = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return MHD_SC_UNEXPECTED_EPOLL_WAIT_ERROR;
|
||||
}
|
||||
for (i = 0; i < (unsigned int) num_events; i++)
|
||||
{
|
||||
struct UpgradeEpollHandle *const ueh = events[i].data.ptr;
|
||||
struct MHD_UpgradeResponseHandle *const urh = ueh->urh;
|
||||
bool new_err_state = false;
|
||||
|
||||
if (urh->clean_ready)
|
||||
continue;
|
||||
|
||||
/* Update ueh state based on what is ready according to epoll() */
|
||||
if (0 != (events[i].events & EPOLLIN))
|
||||
ueh->celi |= MHD_EPOLL_STATE_READ_READY;
|
||||
if (0 != (events[i].events & EPOLLOUT))
|
||||
ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
|
||||
if (0 != (events[i].events & EPOLLHUP))
|
||||
ueh->celi |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY;
|
||||
|
||||
if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
|
||||
(0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
|
||||
{
|
||||
/* Process new error state only one time
|
||||
* and avoid continuously marking this connection
|
||||
* as 'ready'. */
|
||||
ueh->celi |= MHD_EPOLL_STATE_ERROR;
|
||||
new_err_state = true;
|
||||
}
|
||||
|
||||
if (! urh->in_eready_list)
|
||||
{
|
||||
if (new_err_state ||
|
||||
is_urh_ready (urh))
|
||||
{
|
||||
EDLL_insert (daemon->eready_urh_head,
|
||||
daemon->eready_urh_tail,
|
||||
urh);
|
||||
urh->in_eready_list = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
prev = daemon->eready_urh_tail;
|
||||
while (NULL != (pos = prev))
|
||||
{
|
||||
prev = pos->prevE;
|
||||
MHD_upgrade_response_handle_process_ (pos);
|
||||
if (! is_urh_ready (pos))
|
||||
{
|
||||
prev = pos->prevE;
|
||||
MHD_upgrade_response_handle_process_ (pos);
|
||||
if (! is_urh_ready(pos))
|
||||
{
|
||||
EDLL_remove (daemon->eready_urh_head,
|
||||
daemon->eready_urh_tail,
|
||||
pos);
|
||||
pos->in_eready_list = false;
|
||||
}
|
||||
/* Finished forwarding? */
|
||||
if ( (0 == pos->in_buffer_size) &&
|
||||
(0 == pos->out_buffer_size) &&
|
||||
(0 == pos->in_buffer_used) &&
|
||||
(0 == pos->out_buffer_used) )
|
||||
{
|
||||
MHD_connection_finish_forward_ (pos->connection);
|
||||
pos->clean_ready = true;
|
||||
/* If 'pos->was_closed' already was set to true, connection
|
||||
* will be moved immediately to cleanup list. Otherwise
|
||||
* connection will stay in suspended list until 'pos' will
|
||||
* be marked with 'was_closed' by application. */
|
||||
MHD_request_resume (&pos->connection->request);
|
||||
}
|
||||
EDLL_remove (daemon->eready_urh_head,
|
||||
daemon->eready_urh_tail,
|
||||
pos);
|
||||
pos->in_eready_list = false;
|
||||
}
|
||||
/* Finished forwarding? */
|
||||
if ( (0 == pos->in_buffer_size) &&
|
||||
(0 == pos->out_buffer_size) &&
|
||||
(0 == pos->in_buffer_used) &&
|
||||
(0 == pos->out_buffer_used) )
|
||||
{
|
||||
MHD_connection_finish_forward_ (pos->connection);
|
||||
pos->clean_ready = true;
|
||||
/* If 'pos->was_closed' already was set to true, connection
|
||||
* will be moved immediately to cleanup list. Otherwise
|
||||
* connection will stay in suspended list until 'pos' will
|
||||
* be marked with 'was_closed' by application. */
|
||||
MHD_request_resume (&pos->connection->request);
|
||||
}
|
||||
}
|
||||
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
@@ -212,10 +212,10 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon)
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_epoll_ (struct MHD_Daemon *daemon,
|
||||
bool may_block)
|
||||
bool may_block)
|
||||
{
|
||||
#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
|
||||
static const char * const upgrade_marker = "upgrade_ptr";
|
||||
static const char *const upgrade_marker = "upgrade_ptr";
|
||||
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
|
||||
struct MHD_Connection *pos;
|
||||
struct MHD_Connection *prev;
|
||||
@@ -239,24 +239,24 @@ MHD_daemon_epoll_ (struct MHD_Daemon *daemon,
|
||||
(daemon->connections < daemon->global_connection_limit) &&
|
||||
(! daemon->listen_socket_in_epoll) &&
|
||||
(! daemon->at_limit) )
|
||||
{
|
||||
event.events = EPOLLIN;
|
||||
event.data.ptr = daemon;
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_ADD,
|
||||
ls,
|
||||
&event))
|
||||
{
|
||||
event.events = EPOLLIN;
|
||||
event.data.ptr = daemon;
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_ADD,
|
||||
ls,
|
||||
&event))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_ADD_FAILED,
|
||||
_("Call to epoll_ctl failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_ADD_FAILED,
|
||||
_ ("Call to epoll_ctl failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_SC_EPOLL_CTL_ADD_FAILED;
|
||||
}
|
||||
daemon->listen_socket_in_epoll = true;
|
||||
return MHD_SC_EPOLL_CTL_ADD_FAILED;
|
||||
}
|
||||
daemon->listen_socket_in_epoll = true;
|
||||
}
|
||||
if ( (daemon->was_quiesced) &&
|
||||
(daemon->listen_socket_in_epoll) )
|
||||
{
|
||||
@@ -271,58 +271,58 @@ MHD_daemon_epoll_ (struct MHD_Daemon *daemon,
|
||||
#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
|
||||
if ( (! daemon->upgrade_fd_in_epoll) &&
|
||||
(-1 != daemon->epoll_upgrade_fd) )
|
||||
{
|
||||
event.events = EPOLLIN | EPOLLOUT;
|
||||
event.data.ptr = (void *) upgrade_marker;
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_ADD,
|
||||
daemon->epoll_upgrade_fd,
|
||||
&event))
|
||||
{
|
||||
event.events = EPOLLIN | EPOLLOUT;
|
||||
event.data.ptr = (void *) upgrade_marker;
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_ADD,
|
||||
daemon->epoll_upgrade_fd,
|
||||
&event))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_ADD_FAILED,
|
||||
_("Call to epoll_ctl failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_ADD_FAILED,
|
||||
_ ("Call to epoll_ctl failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_SC_EPOLL_CTL_ADD_FAILED;
|
||||
}
|
||||
daemon->upgrade_fd_in_epoll = true;
|
||||
return MHD_SC_EPOLL_CTL_ADD_FAILED;
|
||||
}
|
||||
daemon->upgrade_fd_in_epoll = true;
|
||||
}
|
||||
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
|
||||
if ( (daemon->listen_socket_in_epoll) &&
|
||||
( (daemon->connections == daemon->global_connection_limit) ||
|
||||
(daemon->at_limit) ||
|
||||
(daemon->was_quiesced) ) )
|
||||
{
|
||||
/* we're at the connection limit, disable listen socket
|
||||
for event loop for now */
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_DEL,
|
||||
ls,
|
||||
NULL))
|
||||
MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
|
||||
daemon->listen_socket_in_epoll = false;
|
||||
}
|
||||
{
|
||||
/* we're at the connection limit, disable listen socket
|
||||
for event loop for now */
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_DEL,
|
||||
ls,
|
||||
NULL))
|
||||
MHD_PANIC (_ ("Failed to remove listen FD from epoll set\n"));
|
||||
daemon->listen_socket_in_epoll = false;
|
||||
}
|
||||
|
||||
if ( (! daemon->disallow_suspend_resume) &&
|
||||
(MHD_resume_suspended_connections_ (daemon)) )
|
||||
may_block = false;
|
||||
|
||||
if (may_block)
|
||||
{
|
||||
if (MHD_SC_OK == /* FIXME: distinguish between NO_TIMEOUT and errors */
|
||||
MHD_daemon_get_timeout (daemon,
|
||||
&timeout_ll))
|
||||
{
|
||||
if (MHD_SC_OK == /* FIXME: distinguish between NO_TIMEOUT and errors */
|
||||
MHD_daemon_get_timeout (daemon,
|
||||
&timeout_ll))
|
||||
{
|
||||
if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
|
||||
timeout_ms = INT_MAX;
|
||||
else
|
||||
timeout_ms = (int) timeout_ll;
|
||||
}
|
||||
if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
|
||||
timeout_ms = INT_MAX;
|
||||
else
|
||||
timeout_ms = -1;
|
||||
timeout_ms = (int) timeout_ll;
|
||||
}
|
||||
else
|
||||
timeout_ms = -1;
|
||||
}
|
||||
else
|
||||
timeout_ms = 0;
|
||||
|
||||
@@ -337,113 +337,114 @@ MHD_daemon_epoll_ (struct MHD_Daemon *daemon,
|
||||
than unfair behavior... */
|
||||
num_events = MAX_EVENTS;
|
||||
while (MAX_EVENTS == num_events)
|
||||
{
|
||||
/* update event masks */
|
||||
num_events = epoll_wait (daemon->epoll_fd,
|
||||
events,
|
||||
MAX_EVENTS,
|
||||
timeout_ms);
|
||||
if (-1 == num_events)
|
||||
{
|
||||
/* update event masks */
|
||||
num_events = epoll_wait (daemon->epoll_fd,
|
||||
events,
|
||||
MAX_EVENTS,
|
||||
timeout_ms);
|
||||
if (-1 == num_events)
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
return MHD_SC_OK;
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
return MHD_SC_OK;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_UNEXPECTED_EPOLL_WAIT_ERROR,
|
||||
_("Call to epoll_wait failed: %s\n"),
|
||||
MHD_socket_strerr_ (err));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_UNEXPECTED_EPOLL_WAIT_ERROR,
|
||||
_ ("Call to epoll_wait failed: %s\n"),
|
||||
MHD_socket_strerr_ (err));
|
||||
#endif
|
||||
return MHD_SC_UNEXPECTED_EPOLL_WAIT_ERROR;
|
||||
}
|
||||
for (i=0;i<(unsigned int) num_events;i++)
|
||||
{
|
||||
/* First, check for the values of `ptr` that would indicate
|
||||
that this event is not about a normal connection. */
|
||||
if (NULL == events[i].data.ptr)
|
||||
continue; /* shutdown signal! */
|
||||
#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
|
||||
if (upgrade_marker == events[i].data.ptr)
|
||||
{
|
||||
/* activity on an upgraded connection, we process
|
||||
those in a separate epoll() */
|
||||
run_upgraded = true;
|
||||
continue;
|
||||
}
|
||||
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
|
||||
if (daemon->epoll_itc_marker == events[i].data.ptr)
|
||||
{
|
||||
/* It's OK to clear ITC here as all external
|
||||
conditions will be processed later. */
|
||||
MHD_itc_clear_ (daemon->itc);
|
||||
continue;
|
||||
}
|
||||
if (daemon == events[i].data.ptr)
|
||||
{
|
||||
/* Check for error conditions on listen socket. */
|
||||
/* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
|
||||
if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
|
||||
{
|
||||
unsigned int series_length = 0;
|
||||
/* Run 'accept' until it fails or daemon at limit of connections.
|
||||
* Do not accept more then 10 connections at once. The rest will
|
||||
* be accepted on next turn (level trigger is used for listen
|
||||
* socket). */
|
||||
while ( (MHD_SC_OK ==
|
||||
MHD_accept_connection_ (daemon)) &&
|
||||
(series_length < 10) &&
|
||||
(daemon->connections < daemon->global_connection_limit) &&
|
||||
(! daemon->at_limit) )
|
||||
series_length++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* this is an event relating to a 'normal' connection,
|
||||
remember the event and if appropriate mark the
|
||||
connection as 'eready'. */
|
||||
pos = events[i].data.ptr;
|
||||
/* normal processing: update read/write data */
|
||||
if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
|
||||
{
|
||||
pos->epoll_state |= MHD_EPOLL_STATE_ERROR;
|
||||
if (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
|
||||
{
|
||||
EDLL_insert (daemon->eready_head,
|
||||
daemon->eready_tail,
|
||||
pos);
|
||||
pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 != (events[i].events & EPOLLIN))
|
||||
{
|
||||
pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
|
||||
if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->request.event_loop_info) ||
|
||||
(pos->request.read_buffer_size > pos->request.read_buffer_offset) ) &&
|
||||
(0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
|
||||
{
|
||||
EDLL_insert (daemon->eready_head,
|
||||
daemon->eready_tail,
|
||||
pos);
|
||||
pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
|
||||
}
|
||||
}
|
||||
if (0 != (events[i].events & EPOLLOUT))
|
||||
{
|
||||
pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
|
||||
if ( (MHD_EVENT_LOOP_INFO_WRITE == pos->request.event_loop_info) &&
|
||||
(0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
|
||||
{
|
||||
EDLL_insert (daemon->eready_head,
|
||||
daemon->eready_tail,
|
||||
pos);
|
||||
pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return MHD_SC_UNEXPECTED_EPOLL_WAIT_ERROR;
|
||||
}
|
||||
for (i = 0; i<(unsigned int) num_events; i++)
|
||||
{
|
||||
/* First, check for the values of `ptr` that would indicate
|
||||
that this event is not about a normal connection. */
|
||||
if (NULL == events[i].data.ptr)
|
||||
continue; /* shutdown signal! */
|
||||
#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
|
||||
if (upgrade_marker == events[i].data.ptr)
|
||||
{
|
||||
/* activity on an upgraded connection, we process
|
||||
those in a separate epoll() */
|
||||
run_upgraded = true;
|
||||
continue;
|
||||
}
|
||||
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
|
||||
if (daemon->epoll_itc_marker == events[i].data.ptr)
|
||||
{
|
||||
/* It's OK to clear ITC here as all external
|
||||
conditions will be processed later. */
|
||||
MHD_itc_clear_ (daemon->itc);
|
||||
continue;
|
||||
}
|
||||
if (daemon == events[i].data.ptr)
|
||||
{
|
||||
/* Check for error conditions on listen socket. */
|
||||
/* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
|
||||
if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
|
||||
{
|
||||
unsigned int series_length = 0;
|
||||
/* Run 'accept' until it fails or daemon at limit of connections.
|
||||
* Do not accept more then 10 connections at once. The rest will
|
||||
* be accepted on next turn (level trigger is used for listen
|
||||
* socket). */
|
||||
while ( (MHD_SC_OK ==
|
||||
MHD_accept_connection_ (daemon)) &&
|
||||
(series_length < 10) &&
|
||||
(daemon->connections < daemon->global_connection_limit) &&
|
||||
(! daemon->at_limit) )
|
||||
series_length++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* this is an event relating to a 'normal' connection,
|
||||
remember the event and if appropriate mark the
|
||||
connection as 'eready'. */
|
||||
pos = events[i].data.ptr;
|
||||
/* normal processing: update read/write data */
|
||||
if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
|
||||
{
|
||||
pos->epoll_state |= MHD_EPOLL_STATE_ERROR;
|
||||
if (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
|
||||
{
|
||||
EDLL_insert (daemon->eready_head,
|
||||
daemon->eready_tail,
|
||||
pos);
|
||||
pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 != (events[i].events & EPOLLIN))
|
||||
{
|
||||
pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
|
||||
if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->request.event_loop_info) ||
|
||||
(pos->request.read_buffer_size >
|
||||
pos->request.read_buffer_offset) ) &&
|
||||
(0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
|
||||
{
|
||||
EDLL_insert (daemon->eready_head,
|
||||
daemon->eready_tail,
|
||||
pos);
|
||||
pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
|
||||
}
|
||||
}
|
||||
if (0 != (events[i].events & EPOLLOUT))
|
||||
{
|
||||
pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
|
||||
if ( (MHD_EVENT_LOOP_INFO_WRITE == pos->request.event_loop_info) &&
|
||||
(0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
|
||||
{
|
||||
EDLL_insert (daemon->eready_head,
|
||||
daemon->eready_tail,
|
||||
pos);
|
||||
pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
|
||||
if (run_upgraded)
|
||||
@@ -453,28 +454,32 @@ MHD_daemon_epoll_ (struct MHD_Daemon *daemon,
|
||||
/* process events for connections */
|
||||
prev = daemon->eready_tail;
|
||||
while (NULL != (pos = prev))
|
||||
{
|
||||
prev = pos->prevE;
|
||||
MHD_connection_call_handlers_ (pos,
|
||||
0 != (pos->epoll_state
|
||||
& MHD_EPOLL_STATE_READ_READY),
|
||||
0 != (pos->epoll_state
|
||||
& MHD_EPOLL_STATE_WRITE_READY),
|
||||
0 != (pos->epoll_state
|
||||
& MHD_EPOLL_STATE_ERROR));
|
||||
if (MHD_EPOLL_STATE_IN_EREADY_EDLL ==
|
||||
(pos->epoll_state & (MHD_EPOLL_STATE_SUSPENDED
|
||||
| MHD_EPOLL_STATE_IN_EREADY_EDLL)))
|
||||
{
|
||||
prev = pos->prevE;
|
||||
MHD_connection_call_handlers_ (pos,
|
||||
0 != (pos->epoll_state & MHD_EPOLL_STATE_READ_READY),
|
||||
0 != (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY),
|
||||
0 != (pos->epoll_state & MHD_EPOLL_STATE_ERROR));
|
||||
if (MHD_EPOLL_STATE_IN_EREADY_EDLL ==
|
||||
(pos->epoll_state & (MHD_EPOLL_STATE_SUSPENDED | MHD_EPOLL_STATE_IN_EREADY_EDLL)))
|
||||
{
|
||||
if ( (MHD_EVENT_LOOP_INFO_READ == pos->request.event_loop_info &&
|
||||
0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY) ) ||
|
||||
(MHD_EVENT_LOOP_INFO_WRITE == pos->request.event_loop_info &&
|
||||
0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY) ) ||
|
||||
MHD_EVENT_LOOP_INFO_CLEANUP == pos->request.event_loop_info)
|
||||
{
|
||||
EDLL_remove (daemon->eready_head,
|
||||
daemon->eready_tail,
|
||||
pos);
|
||||
pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
|
||||
}
|
||||
}
|
||||
if ( ((MHD_EVENT_LOOP_INFO_READ == pos->request.event_loop_info) &&
|
||||
(0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ||
|
||||
((MHD_EVENT_LOOP_INFO_WRITE == pos->request.event_loop_info) &&
|
||||
(0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ) ||
|
||||
(MHD_EVENT_LOOP_INFO_CLEANUP == pos->request.event_loop_info) )
|
||||
{
|
||||
EDLL_remove (daemon->eready_head,
|
||||
daemon->eready_tail,
|
||||
pos);
|
||||
pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, handle timed-out connections; we need to do this here
|
||||
as the epoll mechanism won't call the 'MHD_request_handle_idle_()' on everything,
|
||||
@@ -486,22 +491,22 @@ MHD_daemon_epoll_ (struct MHD_Daemon *daemon,
|
||||
do not bother to sort that (presumably very short) list. */
|
||||
prev = daemon->manual_timeout_tail;
|
||||
while (NULL != (pos = prev))
|
||||
{
|
||||
prev = pos->prevX;
|
||||
MHD_request_handle_idle_ (&pos->request);
|
||||
}
|
||||
{
|
||||
prev = pos->prevX;
|
||||
MHD_request_handle_idle_ (&pos->request);
|
||||
}
|
||||
/* Connections with the default timeout are sorted by prepending
|
||||
them to the head of the list whenever we touch the connection;
|
||||
thus it suffices to iterate from the tail until the first
|
||||
connection is NOT timed out */
|
||||
prev = daemon->normal_timeout_tail;
|
||||
while (NULL != (pos = prev))
|
||||
{
|
||||
prev = pos->prevX;
|
||||
MHD_request_handle_idle_ (&pos->request);
|
||||
if (MHD_REQUEST_CLOSED != pos->request.state)
|
||||
break; /* sorted by timeout, no need to visit the rest! */
|
||||
}
|
||||
{
|
||||
prev = pos->prevX;
|
||||
MHD_request_handle_idle_ (&pos->request);
|
||||
if (MHD_REQUEST_CLOSED != pos->request.state)
|
||||
break; /* sorted by timeout, no need to visit the rest! */
|
||||
}
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -38,8 +38,8 @@
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_epoll_ (struct MHD_Daemon *daemon,
|
||||
bool may_block)
|
||||
MHD_NONNULL (1);
|
||||
bool may_block)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_get_timeout (struct MHD_Daemon *daemon,
|
||||
MHD_UNSIGNED_LONG_LONG *timeout)
|
||||
MHD_UNSIGNED_LONG_LONG *timeout)
|
||||
{
|
||||
time_t earliest_deadline;
|
||||
time_t now;
|
||||
@@ -54,71 +54,71 @@ MHD_daemon_get_timeout (struct MHD_Daemon *daemon,
|
||||
bool have_timeout;
|
||||
|
||||
if (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode)
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_CONFIGURATION_MISMATCH_FOR_GET_TIMEOUT,
|
||||
_("Illegal call to MHD_get_timeout\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_CONFIGURATION_MISMATCH_FOR_GET_TIMEOUT,
|
||||
_ ("Illegal call to MHD_get_timeout\n"));
|
||||
#endif
|
||||
return MHD_SC_CONFIGURATION_MISSMATCH_FOR_GET_TIMEOUT;
|
||||
}
|
||||
return MHD_SC_CONFIGURATION_MISSMATCH_FOR_GET_TIMEOUT;
|
||||
}
|
||||
|
||||
if (daemon->data_already_pending)
|
||||
{
|
||||
/* Some data already waiting to be processed. */
|
||||
*timeout = 0;
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
{
|
||||
/* Some data already waiting to be processed. */
|
||||
*timeout = 0;
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
|
||||
#ifdef EPOLL_SUPPORT
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
|
||||
((NULL != daemon->eready_head)
|
||||
#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
|
||||
|| (NULL != daemon->eready_urh_head)
|
||||
|| (NULL != daemon->eready_urh_head)
|
||||
#endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
|
||||
) )
|
||||
{
|
||||
/* Some connection(s) already have some data pending. */
|
||||
*timeout = 0;
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
) )
|
||||
{
|
||||
/* Some connection(s) already have some data pending. */
|
||||
*timeout = 0;
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
#endif /* EPOLL_SUPPORT */
|
||||
|
||||
have_timeout = false;
|
||||
earliest_deadline = 0; /* avoid compiler warnings */
|
||||
for (pos = daemon->manual_timeout_tail; NULL != pos; pos = pos->prevX)
|
||||
{
|
||||
if (0 != pos->connection_timeout)
|
||||
{
|
||||
if (0 != pos->connection_timeout)
|
||||
{
|
||||
if ( (! have_timeout) ||
|
||||
(earliest_deadline - pos->last_activity > pos->connection_timeout) )
|
||||
earliest_deadline = pos->last_activity + pos->connection_timeout;
|
||||
have_timeout = true;
|
||||
}
|
||||
if ( (! have_timeout) ||
|
||||
(earliest_deadline - pos->last_activity > pos->connection_timeout) )
|
||||
earliest_deadline = pos->last_activity + pos->connection_timeout;
|
||||
have_timeout = true;
|
||||
}
|
||||
}
|
||||
/* normal timeouts are sorted, so we only need to look at the 'tail' (oldest) */
|
||||
pos = daemon->normal_timeout_tail;
|
||||
if ( (NULL != pos) &&
|
||||
(0 != pos->connection_timeout) )
|
||||
{
|
||||
if ( (! have_timeout) ||
|
||||
(earliest_deadline - pos->connection_timeout > pos->last_activity) )
|
||||
earliest_deadline = pos->last_activity + pos->connection_timeout;
|
||||
have_timeout = true;
|
||||
}
|
||||
{
|
||||
if ( (! have_timeout) ||
|
||||
(earliest_deadline - pos->connection_timeout > pos->last_activity) )
|
||||
earliest_deadline = pos->last_activity + pos->connection_timeout;
|
||||
have_timeout = true;
|
||||
}
|
||||
|
||||
if (! have_timeout)
|
||||
return MHD_SC_NO_TIMEOUT;
|
||||
now = MHD_monotonic_sec_counter();
|
||||
now = MHD_monotonic_sec_counter ();
|
||||
if (earliest_deadline < now)
|
||||
*timeout = 0;
|
||||
else
|
||||
{
|
||||
const time_t second_left = earliest_deadline - now;
|
||||
if (second_left > ULLONG_MAX / 1000) /* Ignore compiler warning: 'second_left' is always positive. */
|
||||
*timeout = ULLONG_MAX;
|
||||
else
|
||||
*timeout = 1000LL * second_left;
|
||||
{
|
||||
const time_t second_left = earliest_deadline - now;
|
||||
if (second_left > ULLONG_MAX / 1000) /* Ignore compiler warning: 'second_left' is always positive. */
|
||||
*timeout = ULLONG_MAX;
|
||||
else
|
||||
*timeout = 1000LL * second_left;
|
||||
}
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
|
||||
+49
-49
@@ -43,62 +43,62 @@
|
||||
*/
|
||||
enum MHD_Bool
|
||||
MHD_daemon_get_information_sz (struct MHD_Daemon *daemon,
|
||||
enum MHD_DaemonInformationType info_type,
|
||||
union MHD_DaemonInformation *return_value,
|
||||
size_t return_value_size)
|
||||
enum MHD_DaemonInformationType info_type,
|
||||
union MHD_DaemonInformation *return_value,
|
||||
size_t return_value_size)
|
||||
{
|
||||
#define CHECK_SIZE(type) if (sizeof(type) < return_value_size) \
|
||||
#define CHECK_SIZE(type) if (sizeof(type) < return_value_size) \
|
||||
return MHD_NO
|
||||
|
||||
switch (info_type)
|
||||
{
|
||||
case MHD_DAEMON_INFORMATION_LISTEN_SOCKET:
|
||||
CHECK_SIZE (MHD_socket);
|
||||
return_value->listen_socket
|
||||
= daemon->listen_socket;
|
||||
return MHD_YES;
|
||||
{
|
||||
case MHD_DAEMON_INFORMATION_LISTEN_SOCKET:
|
||||
CHECK_SIZE (MHD_socket);
|
||||
return_value->listen_socket
|
||||
= daemon->listen_socket;
|
||||
return MHD_YES;
|
||||
#ifdef EPOLL_SUPPORT
|
||||
case MHD_DAEMON_INFORMATION_EPOLL_FD:
|
||||
CHECK_SIZE (int);
|
||||
// FIXME: maybe return MHD_NO if we are not using EPOLL?
|
||||
return_value->epoll_fd = daemon->epoll_fd;
|
||||
return MHD_YES;
|
||||
case MHD_DAEMON_INFORMATION_EPOLL_FD:
|
||||
CHECK_SIZE (int);
|
||||
// FIXME: maybe return MHD_NO if we are not using EPOLL?
|
||||
return_value->epoll_fd = daemon->epoll_fd;
|
||||
return MHD_YES;
|
||||
#endif
|
||||
case MHD_DAEMON_INFORMATION_CURRENT_CONNECTIONS:
|
||||
CHECK_SIZE (unsigned int);
|
||||
if (MHD_TM_EXTERNAL_EVENT_LOOP == daemon->threading_mode)
|
||||
{
|
||||
/* Assumes that MHD_run() in not called in other thread
|
||||
(of the application) at the same time. */
|
||||
MHD_connection_cleanup_ (daemon);
|
||||
return_value->num_connections
|
||||
= daemon->connections;
|
||||
}
|
||||
else if (daemon->worker_pool)
|
||||
{
|
||||
unsigned int i;
|
||||
/* Collect the connection information stored in the workers. */
|
||||
return_value->num_connections = 0;
|
||||
for (i = 0; i < daemon->worker_pool_size; i++)
|
||||
{
|
||||
/* FIXME: next line is thread-safe only if read is atomic. */
|
||||
return_value->num_connections
|
||||
+= daemon->worker_pool[i].connections;
|
||||
}
|
||||
}
|
||||
else
|
||||
return_value->num_connections
|
||||
= daemon->connections;
|
||||
return MHD_YES;
|
||||
case MHD_DAEMON_INFORMATION_BIND_PORT:
|
||||
CHECK_SIZE (uint16_t);
|
||||
// FIXME: return MHD_NO if port is not known/UNIX?
|
||||
return_value->port = daemon->listen_port;
|
||||
return MHD_YES;
|
||||
default:
|
||||
return MHD_NO;
|
||||
case MHD_DAEMON_INFORMATION_CURRENT_CONNECTIONS:
|
||||
CHECK_SIZE (unsigned int);
|
||||
if (MHD_TM_EXTERNAL_EVENT_LOOP == daemon->threading_mode)
|
||||
{
|
||||
/* Assumes that MHD_run() in not called in other thread
|
||||
(of the application) at the same time. */
|
||||
MHD_connection_cleanup_ (daemon);
|
||||
return_value->num_connections
|
||||
= daemon->connections;
|
||||
}
|
||||
|
||||
else if (daemon->worker_pool)
|
||||
{
|
||||
unsigned int i;
|
||||
/* Collect the connection information stored in the workers. */
|
||||
return_value->num_connections = 0;
|
||||
for (i = 0; i < daemon->worker_pool_size; i++)
|
||||
{
|
||||
/* FIXME: next line is thread-safe only if read is atomic. */
|
||||
return_value->num_connections
|
||||
+= daemon->worker_pool[i].connections;
|
||||
}
|
||||
}
|
||||
else
|
||||
return_value->num_connections
|
||||
= daemon->connections;
|
||||
return MHD_YES;
|
||||
case MHD_DAEMON_INFORMATION_BIND_PORT:
|
||||
CHECK_SIZE (uint16_t);
|
||||
// FIXME: return MHD_NO if port is not known/UNIX?
|
||||
return_value->port = daemon->listen_port;
|
||||
return MHD_YES;
|
||||
default:
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
#undef CHECK_SIZE
|
||||
}
|
||||
|
||||
|
||||
+59
-59
@@ -89,7 +89,7 @@ get_master (struct MHD_Daemon *daemon)
|
||||
static void
|
||||
MHD_ip_count_lock (struct MHD_Daemon *daemon)
|
||||
{
|
||||
MHD_mutex_lock_chk_(&daemon->per_ip_connection_mutex);
|
||||
MHD_mutex_lock_chk_ (&daemon->per_ip_connection_mutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ MHD_ip_count_lock (struct MHD_Daemon *daemon)
|
||||
static void
|
||||
MHD_ip_count_unlock (struct MHD_Daemon *daemon)
|
||||
{
|
||||
MHD_mutex_unlock_chk_(&daemon->per_ip_connection_mutex);
|
||||
MHD_mutex_unlock_chk_ (&daemon->per_ip_connection_mutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -135,37 +135,37 @@ MHD_ip_addr_compare (const void *a1,
|
||||
*/
|
||||
static int
|
||||
MHD_ip_addr_to_key (const struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
struct MHD_IPCount *key)
|
||||
socklen_t addrlen,
|
||||
struct MHD_IPCount *key)
|
||||
{
|
||||
memset(key,
|
||||
0,
|
||||
sizeof(*key));
|
||||
memset (key,
|
||||
0,
|
||||
sizeof(*key));
|
||||
|
||||
/* IPv4 addresses */
|
||||
if (sizeof (struct sockaddr_in) == addrlen)
|
||||
{
|
||||
const struct sockaddr_in *addr4 = (const struct sockaddr_in*) addr;
|
||||
{
|
||||
const struct sockaddr_in *addr4 = (const struct sockaddr_in*) addr;
|
||||
|
||||
key->family = AF_INET;
|
||||
memcpy (&key->addr.ipv4,
|
||||
&addr4->sin_addr,
|
||||
sizeof(addr4->sin_addr));
|
||||
return MHD_YES;
|
||||
}
|
||||
key->family = AF_INET;
|
||||
memcpy (&key->addr.ipv4,
|
||||
&addr4->sin_addr,
|
||||
sizeof(addr4->sin_addr));
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
#if HAVE_INET6
|
||||
/* IPv6 addresses */
|
||||
if (sizeof (struct sockaddr_in6) == addrlen)
|
||||
{
|
||||
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*) addr;
|
||||
{
|
||||
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*) addr;
|
||||
|
||||
key->family = AF_INET6;
|
||||
memcpy (&key->addr.ipv6,
|
||||
&addr6->sin6_addr,
|
||||
sizeof(addr6->sin6_addr));
|
||||
return MHD_YES;
|
||||
}
|
||||
key->family = AF_INET6;
|
||||
memcpy (&key->addr.ipv6,
|
||||
&addr6->sin6_addr,
|
||||
sizeof(addr6->sin6_addr));
|
||||
return MHD_YES;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Some other address */
|
||||
@@ -186,8 +186,8 @@ MHD_ip_addr_to_key (const struct sockaddr *addr,
|
||||
*/
|
||||
int
|
||||
MHD_ip_limit_add (struct MHD_Daemon *daemon,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
struct MHD_IPCount *key;
|
||||
void **nodep;
|
||||
@@ -206,31 +206,31 @@ MHD_ip_limit_add (struct MHD_Daemon *daemon,
|
||||
if (MHD_NO == MHD_ip_addr_to_key (addr,
|
||||
addrlen,
|
||||
key))
|
||||
{
|
||||
/* Allow unhandled address types through */
|
||||
free (key);
|
||||
return MHD_YES;
|
||||
}
|
||||
{
|
||||
/* Allow unhandled address types through */
|
||||
free (key);
|
||||
return MHD_YES;
|
||||
}
|
||||
MHD_ip_count_lock (daemon);
|
||||
|
||||
/* Search for the IP address */
|
||||
if (NULL == (nodep = tsearch (key,
|
||||
&daemon->per_ip_connection_count,
|
||||
&MHD_ip_addr_compare)))
|
||||
{
|
||||
&daemon->per_ip_connection_count,
|
||||
&MHD_ip_addr_compare)))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_IP_COUNTER_FAILURE,
|
||||
_("Failed to add IP connection count node\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_IP_COUNTER_FAILURE,
|
||||
_ ("Failed to add IP connection count node\n"));
|
||||
#endif
|
||||
MHD_ip_count_unlock (daemon);
|
||||
free (key);
|
||||
return MHD_NO;
|
||||
}
|
||||
MHD_ip_count_unlock (daemon);
|
||||
free (key);
|
||||
return MHD_NO;
|
||||
}
|
||||
node = *nodep;
|
||||
/* If we got an existing node back, free the one we created */
|
||||
if (node != key)
|
||||
free(key);
|
||||
free (key);
|
||||
key = (struct MHD_IPCount *) node;
|
||||
/* Test if there is room for another connection; if so,
|
||||
* increment count */
|
||||
@@ -253,8 +253,8 @@ MHD_ip_limit_add (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_ip_limit_del (struct MHD_Daemon *daemon,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
struct MHD_IPCount search_key;
|
||||
struct MHD_IPCount *found_key;
|
||||
@@ -274,27 +274,27 @@ MHD_ip_limit_del (struct MHD_Daemon *daemon,
|
||||
|
||||
/* Search for the IP address */
|
||||
if (NULL == (nodep = tfind (&search_key,
|
||||
&daemon->per_ip_connection_count,
|
||||
&MHD_ip_addr_compare)))
|
||||
{
|
||||
/* Something's wrong if we couldn't find an IP address
|
||||
* that was previously added */
|
||||
MHD_PANIC (_("Failed to find previously-added IP address\n"));
|
||||
}
|
||||
&daemon->per_ip_connection_count,
|
||||
&MHD_ip_addr_compare)))
|
||||
{
|
||||
/* Something's wrong if we couldn't find an IP address
|
||||
* that was previously added */
|
||||
MHD_PANIC (_ ("Failed to find previously-added IP address\n"));
|
||||
}
|
||||
found_key = (struct MHD_IPCount *) *nodep;
|
||||
/* Validate existing count for IP address */
|
||||
if (0 == found_key->count)
|
||||
{
|
||||
MHD_PANIC (_("Previously-added IP address had counter of zero\n"));
|
||||
}
|
||||
{
|
||||
MHD_PANIC (_ ("Previously-added IP address had counter of zero\n"));
|
||||
}
|
||||
/* Remove the node entirely if count reduces to 0 */
|
||||
if (0 == --found_key->count)
|
||||
{
|
||||
tdelete (found_key,
|
||||
&daemon->per_ip_connection_count,
|
||||
&MHD_ip_addr_compare);
|
||||
free (found_key);
|
||||
}
|
||||
{
|
||||
tdelete (found_key,
|
||||
&daemon->per_ip_connection_count,
|
||||
&MHD_ip_addr_compare);
|
||||
free (found_key);
|
||||
}
|
||||
|
||||
MHD_ip_count_unlock (daemon);
|
||||
}
|
||||
|
||||
@@ -38,9 +38,9 @@
|
||||
*/
|
||||
int
|
||||
MHD_ip_limit_add (struct MHD_Daemon *daemon,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
MHD_NONNULL (1,2);
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
MHD_NONNULL (1,2);
|
||||
|
||||
|
||||
/**
|
||||
@@ -53,8 +53,8 @@ MHD_ip_limit_add (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_ip_limit_del (struct MHD_Daemon *daemon,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
MHD_NONNULL (1,2);
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
MHD_NONNULL (1,2);
|
||||
|
||||
#endif
|
||||
|
||||
+72
-72
@@ -38,8 +38,8 @@
|
||||
*/
|
||||
void
|
||||
MHD_daemon_set_logger (struct MHD_Daemon *daemon,
|
||||
MHD_LoggingCallback logger,
|
||||
void *logger_cls)
|
||||
MHD_LoggingCallback logger,
|
||||
void *logger_cls)
|
||||
{
|
||||
daemon->logger = logger;
|
||||
daemon->logger_cls = logger_cls;
|
||||
@@ -148,8 +148,8 @@ MHD_daemon_disallow_upgrade (struct MHD_Daemon *daemon)
|
||||
*/
|
||||
enum MHD_Bool
|
||||
MHD_daemon_tcp_fastopen (struct MHD_Daemon *daemon,
|
||||
enum MHD_FastOpenMethod fom,
|
||||
unsigned int queue_length)
|
||||
enum MHD_FastOpenMethod fom,
|
||||
unsigned int queue_length)
|
||||
{
|
||||
daemon->fast_open_method = fom;
|
||||
daemon->fo_queue_length = queue_length;
|
||||
@@ -185,8 +185,8 @@ MHD_daemon_tcp_fastopen (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_bind_port (struct MHD_Daemon *daemon,
|
||||
enum MHD_AddressFamily af,
|
||||
uint16_t port)
|
||||
enum MHD_AddressFamily af,
|
||||
uint16_t port)
|
||||
{
|
||||
daemon->listen_af = af;
|
||||
daemon->listen_port = port;
|
||||
@@ -204,12 +204,12 @@ MHD_daemon_bind_port (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_bind_socket_address (struct MHD_Daemon *daemon,
|
||||
const struct sockaddr *sa,
|
||||
size_t sa_len)
|
||||
const struct sockaddr *sa,
|
||||
size_t sa_len)
|
||||
{
|
||||
memcpy (&daemon->listen_sa,
|
||||
sa,
|
||||
sa_len);
|
||||
sa,
|
||||
sa_len);
|
||||
daemon->listen_sa_len = sa_len;
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ MHD_daemon_bind_socket_address (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_listen_backlog (struct MHD_Daemon *daemon,
|
||||
int listen_backlog)
|
||||
int listen_backlog)
|
||||
{
|
||||
daemon->listen_backlog = listen_backlog;
|
||||
}
|
||||
@@ -275,7 +275,7 @@ MHD_daemon_enable_shoutcast (struct MHD_Daemon *daemon)
|
||||
*/
|
||||
void
|
||||
MHD_daemon_listen_socket (struct MHD_Daemon *daemon,
|
||||
MHD_socket listen_socket)
|
||||
MHD_socket listen_socket)
|
||||
{
|
||||
daemon->listen_socket = listen_socket;
|
||||
}
|
||||
@@ -290,7 +290,7 @@ MHD_daemon_listen_socket (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_Bool
|
||||
MHD_daemon_event_loop (struct MHD_Daemon *daemon,
|
||||
enum MHD_EventLoopSyscall els)
|
||||
enum MHD_EventLoopSyscall els)
|
||||
{
|
||||
switch (els)
|
||||
{
|
||||
@@ -326,7 +326,7 @@ MHD_daemon_event_loop (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_protocol_strict_level (struct MHD_Daemon *daemon,
|
||||
enum MHD_ProtocolStrictLevel sl)
|
||||
enum MHD_ProtocolStrictLevel sl)
|
||||
{
|
||||
daemon->protocol_strict_level = sl;
|
||||
}
|
||||
@@ -349,8 +349,8 @@ MHD_daemon_protocol_strict_level (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_set_tls_backend (struct MHD_Daemon *daemon,
|
||||
const char *tls_backend,
|
||||
const char *ciphers)
|
||||
const char *tls_backend,
|
||||
const char *ciphers)
|
||||
{
|
||||
#if ! (defined(HTTPS_SUPPORT) && defined (HAVE_DLFCN_H))
|
||||
return MHD_SC_TLS_DISABLED;
|
||||
@@ -361,18 +361,18 @@ MHD_daemon_set_tls_backend (struct MHD_Daemon *daemon,
|
||||
|
||||
/* todo: .dll on W32? */
|
||||
res = MHD_snprintf_ (filename,
|
||||
sizeof (filename),
|
||||
"%s/libmicrohttpd_tls_%s.so",
|
||||
MHD_PLUGIN_INSTALL_PREFIX,
|
||||
tls_backend);
|
||||
sizeof (filename),
|
||||
"%s/libmicrohttpd_tls_%s.so",
|
||||
MHD_PLUGIN_INSTALL_PREFIX,
|
||||
tls_backend);
|
||||
if (0 >= res)
|
||||
return MHD_SC_TLS_BACKEND_UNSUPPORTED; /* string too long? */
|
||||
if (NULL ==
|
||||
(daemon->tls_backend_lib = dlopen (filename,
|
||||
RTLD_NOW | RTLD_LOCAL)))
|
||||
RTLD_NOW | RTLD_LOCAL)))
|
||||
return MHD_SC_TLS_BACKEND_UNSUPPORTED; /* plugin not found */
|
||||
if (NULL == (init = dlsym (daemon->tls_backend_lib,
|
||||
"MHD_TLS_init_" MHD_TLS_ABI_VERSION_STR)))
|
||||
"MHD_TLS_init_" MHD_TLS_ABI_VERSION_STR)))
|
||||
|
||||
{
|
||||
dlclose (daemon->tls_backend_lib);
|
||||
@@ -405,9 +405,9 @@ MHD_daemon_set_tls_backend (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_tls_key_and_cert_from_memory (struct MHD_Daemon *daemon,
|
||||
const char *mem_key,
|
||||
const char *mem_cert,
|
||||
const char *pass)
|
||||
const char *mem_key,
|
||||
const char *mem_cert,
|
||||
const char *pass)
|
||||
{
|
||||
#ifndef HTTPS_SUPPORT
|
||||
return MHD_SC_TLS_DISABLED;
|
||||
@@ -417,9 +417,9 @@ MHD_daemon_tls_key_and_cert_from_memory (struct MHD_Daemon *daemon,
|
||||
if (NULL == (plugin = daemon->tls_api))
|
||||
return MHD_SC_TLS_BACKEND_UNINITIALIZED;
|
||||
return plugin->init_kcp (plugin->cls,
|
||||
mem_key,
|
||||
mem_cert,
|
||||
pass);
|
||||
mem_key,
|
||||
mem_cert,
|
||||
pass);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -435,7 +435,7 @@ MHD_daemon_tls_key_and_cert_from_memory (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_tls_mem_dhparams (struct MHD_Daemon *daemon,
|
||||
const char *dh)
|
||||
const char *dh)
|
||||
{
|
||||
#ifndef HTTPS_SUPPORT
|
||||
return MHD_SC_TLS_DISABLED;
|
||||
@@ -445,7 +445,7 @@ MHD_daemon_tls_mem_dhparams (struct MHD_Daemon *daemon,
|
||||
if (NULL == (plugin = daemon->tls_api))
|
||||
return MHD_SC_TLS_BACKEND_UNINITIALIZED;
|
||||
return plugin->init_dhparams (plugin->cls,
|
||||
dh);
|
||||
dh);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -461,7 +461,7 @@ MHD_daemon_tls_mem_dhparams (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_tls_mem_trust (struct MHD_Daemon *daemon,
|
||||
const char *mem_trust)
|
||||
const char *mem_trust)
|
||||
{
|
||||
#ifndef HTTPS_SUPPORT
|
||||
return MHD_SC_TLS_DISABLED;
|
||||
@@ -471,7 +471,7 @@ MHD_daemon_tls_mem_trust (struct MHD_Daemon *daemon,
|
||||
if (NULL == (plugin = daemon->tls_api))
|
||||
return MHD_SC_TLS_BACKEND_UNINITIALIZED;
|
||||
return plugin->init_mem_trust (plugin->cls,
|
||||
mem_trust);
|
||||
mem_trust);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -485,7 +485,7 @@ MHD_daemon_tls_mem_trust (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_gnutls_credentials (struct MHD_Daemon *daemon,
|
||||
int gnutls_credentials)
|
||||
int gnutls_credentials)
|
||||
{
|
||||
#ifndef HTTPS_SUPPORT
|
||||
return MHD_SC_TLS_DISABLED;
|
||||
@@ -518,7 +518,7 @@ MHD_daemon_gnutls_credentials (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_gnutls_key_and_cert_from_callback (struct MHD_Daemon *daemon,
|
||||
void *cb)
|
||||
void *cb)
|
||||
{
|
||||
#ifndef HTTPS_SUPPORT
|
||||
return MHD_SC_TLS_DISABLED;
|
||||
@@ -541,7 +541,7 @@ MHD_daemon_gnutls_key_and_cert_from_callback (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_threading_mode (struct MHD_Daemon *daemon,
|
||||
enum MHD_ThreadingMode tm)
|
||||
enum MHD_ThreadingMode tm)
|
||||
{
|
||||
daemon->threading_mode = tm;
|
||||
}
|
||||
@@ -558,8 +558,8 @@ MHD_daemon_threading_mode (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_accept_policy (struct MHD_Daemon *daemon,
|
||||
MHD_AcceptPolicyCallback apc,
|
||||
void *apc_cls)
|
||||
MHD_AcceptPolicyCallback apc,
|
||||
void *apc_cls)
|
||||
{
|
||||
daemon->accept_policy_cb = apc;
|
||||
daemon->accept_policy_cb_cls = apc_cls;
|
||||
@@ -577,8 +577,8 @@ MHD_daemon_accept_policy (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_set_early_uri_logger (struct MHD_Daemon *daemon,
|
||||
MHD_EarlyUriLogCallback cb,
|
||||
void *cb_cls)
|
||||
MHD_EarlyUriLogCallback cb,
|
||||
void *cb_cls)
|
||||
{
|
||||
daemon->early_uri_logger_cb = cb;
|
||||
daemon->early_uri_logger_cb_cls = cb_cls;
|
||||
@@ -595,8 +595,8 @@ MHD_daemon_set_early_uri_logger (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_set_notify_connection (struct MHD_Daemon *daemon,
|
||||
MHD_NotifyConnectionCallback ncc,
|
||||
void *ncc_cls)
|
||||
MHD_NotifyConnectionCallback ncc,
|
||||
void *ncc_cls)
|
||||
{
|
||||
daemon->notify_connection_cb = ncc;
|
||||
daemon->notify_connection_cb_cls = ncc_cls;
|
||||
@@ -616,8 +616,8 @@ MHD_daemon_set_notify_connection (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_connection_memory_limit (struct MHD_Daemon *daemon,
|
||||
size_t memory_limit_b,
|
||||
size_t memory_increment_b)
|
||||
size_t memory_limit_b,
|
||||
size_t memory_increment_b)
|
||||
{
|
||||
if (memory_increment_b >= memory_limit_b)
|
||||
MHD_PANIC ("sane memory increment must be below memory limit");
|
||||
@@ -636,7 +636,7 @@ MHD_daemon_connection_memory_limit (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_thread_stack_size (struct MHD_Daemon *daemon,
|
||||
size_t stack_limit_b)
|
||||
size_t stack_limit_b)
|
||||
{
|
||||
daemon->thread_stack_limit_b = stack_limit_b;
|
||||
}
|
||||
@@ -659,8 +659,8 @@ MHD_daemon_thread_stack_size (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_connection_limits (struct MHD_Daemon *daemon,
|
||||
unsigned int global_connection_limit,
|
||||
unsigned int ip_connection_limit)
|
||||
unsigned int global_connection_limit,
|
||||
unsigned int ip_connection_limit)
|
||||
{
|
||||
daemon->global_connection_limit = global_connection_limit;
|
||||
daemon->ip_connection_limit = ip_connection_limit;
|
||||
@@ -677,7 +677,7 @@ MHD_daemon_connection_limits (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_connection_default_timeout (struct MHD_Daemon *daemon,
|
||||
unsigned int timeout_s)
|
||||
unsigned int timeout_s)
|
||||
{
|
||||
daemon->connection_default_timeout = (time_t) timeout_s;
|
||||
}
|
||||
@@ -696,8 +696,8 @@ MHD_daemon_connection_default_timeout (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_unescape_cb (struct MHD_Daemon *daemon,
|
||||
MHD_UnescapeCallback unescape_cb,
|
||||
void *unescape_cb_cls)
|
||||
MHD_UnescapeCallback unescape_cb,
|
||||
void *unescape_cb_cls)
|
||||
{
|
||||
daemon->unescape_cb = unescape_cb;
|
||||
daemon->unescape_cb_cls = unescape_cb_cls;
|
||||
@@ -715,8 +715,8 @@ MHD_daemon_unescape_cb (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_digest_auth_random (struct MHD_Daemon *daemon,
|
||||
size_t buf_size,
|
||||
const void *buf)
|
||||
size_t buf_size,
|
||||
const void *buf)
|
||||
{
|
||||
#if ENABLE_DAUTH
|
||||
daemon->digest_auth_random_buf = buf;
|
||||
@@ -739,34 +739,34 @@ MHD_daemon_digest_auth_random (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_digest_auth_nc_length (struct MHD_Daemon *daemon,
|
||||
size_t nc_length)
|
||||
size_t nc_length)
|
||||
{
|
||||
#if ENABLE_DAUTH
|
||||
if ( ( (size_t) (nc_length * sizeof (struct MHD_NonceNc))) /
|
||||
sizeof (struct MHD_NonceNc) != nc_length)
|
||||
if ( ( (size_t) (nc_length * sizeof (struct MHD_NonceNc)))
|
||||
/ sizeof (struct MHD_NonceNc) != nc_length)
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
_ ("Specified value for NC_SIZE too large\n"));
|
||||
#endif
|
||||
return MHD_SC_DIGEST_AUTH_NC_LENGTH_TOO_BIG;
|
||||
}
|
||||
if (0 < nc_length)
|
||||
{
|
||||
if (NULL != daemon->nnc)
|
||||
free (daemon->nnc);
|
||||
daemon->nnc = malloc (daemon->nonce_nc_size
|
||||
* sizeof (struct MHD_NonceNc));
|
||||
if (NULL == daemon->nnc)
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
_("Specified value for NC_SIZE too large\n"));
|
||||
_ ("Failed to allocate memory for nonce-nc map: %s\n"),
|
||||
MHD_strerror_ (errno));
|
||||
#endif
|
||||
return MHD_SC_DIGEST_AUTH_NC_LENGTH_TOO_BIG;
|
||||
}
|
||||
if (0 < nc_length)
|
||||
{
|
||||
if (NULL != daemon->nnc)
|
||||
free (daemon->nnc);
|
||||
daemon->nnc = malloc (daemon->nonce_nc_size *
|
||||
sizeof (struct MHD_NonceNc));
|
||||
if (NULL == daemon->nnc)
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
_("Failed to allocate memory for nonce-nc map: %s\n"),
|
||||
MHD_strerror_ (errno));
|
||||
#endif
|
||||
return MHD_SC_DIGEST_AUTH_NC_ALLOCATION_FAILURE;
|
||||
}
|
||||
return MHD_SC_DIGEST_AUTH_NC_ALLOCATION_FAILURE;
|
||||
}
|
||||
}
|
||||
daemon->digest_nc_length = nc_length;
|
||||
return MHD_SC_OK;
|
||||
#else
|
||||
|
||||
+187
-185
@@ -45,7 +45,7 @@
|
||||
*/
|
||||
static void
|
||||
urh_update_pollfd (struct MHD_UpgradeResponseHandle *urh,
|
||||
struct pollfd p[2])
|
||||
struct pollfd p[2])
|
||||
{
|
||||
p[0].events = 0;
|
||||
p[1].events = 0;
|
||||
@@ -86,12 +86,12 @@ urh_update_pollfd (struct MHD_UpgradeResponseHandle *urh,
|
||||
*/
|
||||
static void
|
||||
urh_to_pollfd (struct MHD_UpgradeResponseHandle *urh,
|
||||
struct pollfd p[2])
|
||||
struct pollfd p[2])
|
||||
{
|
||||
p[0].fd = urh->connection->socket_fd;
|
||||
p[1].fd = urh->mhd.socket;
|
||||
urh_update_pollfd (urh,
|
||||
p);
|
||||
p);
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ urh_to_pollfd (struct MHD_UpgradeResponseHandle *urh,
|
||||
*/
|
||||
static void
|
||||
urh_from_pollfd (struct MHD_UpgradeResponseHandle *urh,
|
||||
struct pollfd p[2])
|
||||
struct pollfd p[2])
|
||||
{
|
||||
/* Reset read/write ready, preserve error state. */
|
||||
urh->app.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
|
||||
@@ -138,7 +138,7 @@ urh_from_pollfd (struct MHD_UpgradeResponseHandle *urh,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_poll_all_ (struct MHD_Daemon *daemon,
|
||||
bool may_block)
|
||||
bool may_block)
|
||||
{
|
||||
unsigned int num_connections;
|
||||
struct MHD_Connection *pos;
|
||||
@@ -171,103 +171,103 @@ MHD_daemon_poll_all_ (struct MHD_Daemon *daemon,
|
||||
MHD_socket ls;
|
||||
|
||||
p = MHD_calloc_ ((2 + num_connections),
|
||||
sizeof (struct pollfd));
|
||||
sizeof (struct pollfd));
|
||||
if (NULL == p)
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_POLL_MALLOC_FAILURE,
|
||||
_("Error allocating memory: %s\n"),
|
||||
MHD_strerror_(errno));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_POLL_MALLOC_FAILURE,
|
||||
_ ("Error allocating memory: %s\n"),
|
||||
MHD_strerror_ (errno));
|
||||
#endif
|
||||
return MHD_SC_POLL_MALLOC_FAILURE;
|
||||
}
|
||||
return MHD_SC_POLL_MALLOC_FAILURE;
|
||||
}
|
||||
poll_server = 0;
|
||||
poll_listen = -1;
|
||||
if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_socket)) &&
|
||||
(! daemon->was_quiesced) &&
|
||||
(daemon->connections < daemon->global_connection_limit) &&
|
||||
(daemon->connections < daemon->global_connection_limit) &&
|
||||
(! daemon->at_limit) )
|
||||
{
|
||||
/* only listen if we are not at the connection limit */
|
||||
p[poll_server].fd = ls;
|
||||
p[poll_server].events = POLLIN;
|
||||
p[poll_server].revents = 0;
|
||||
poll_listen = (int) poll_server;
|
||||
poll_server++;
|
||||
}
|
||||
{
|
||||
/* only listen if we are not at the connection limit */
|
||||
p[poll_server].fd = ls;
|
||||
p[poll_server].events = POLLIN;
|
||||
p[poll_server].revents = 0;
|
||||
poll_listen = (int) poll_server;
|
||||
poll_server++;
|
||||
}
|
||||
poll_itc_idx = -1;
|
||||
if (MHD_ITC_IS_VALID_(daemon->itc))
|
||||
{
|
||||
p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
|
||||
p[poll_server].events = POLLIN;
|
||||
p[poll_server].revents = 0;
|
||||
poll_itc_idx = (int) poll_server;
|
||||
poll_server++;
|
||||
}
|
||||
if (MHD_ITC_IS_VALID_ (daemon->itc))
|
||||
{
|
||||
p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
|
||||
p[poll_server].events = POLLIN;
|
||||
p[poll_server].revents = 0;
|
||||
poll_itc_idx = (int) poll_server;
|
||||
poll_server++;
|
||||
}
|
||||
if (! may_block)
|
||||
timeout = 0;
|
||||
else if ( (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) ||
|
||||
(MHD_SC_OK != /* FIXME: distinguish between NO_TIMEOUT and errors! */
|
||||
MHD_daemon_get_timeout (daemon,
|
||||
<imeout)) )
|
||||
(MHD_SC_OK != /* FIXME: distinguish between NO_TIMEOUT and errors! */
|
||||
MHD_daemon_get_timeout (daemon,
|
||||
<imeout)) )
|
||||
timeout = -1;
|
||||
else
|
||||
timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
|
||||
|
||||
i = 0;
|
||||
for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
|
||||
{
|
||||
p[poll_server + i].fd = pos->socket_fd;
|
||||
switch (pos->request.event_loop_info)
|
||||
{
|
||||
p[poll_server+i].fd = pos->socket_fd;
|
||||
switch (pos->request.event_loop_info)
|
||||
{
|
||||
case MHD_EVENT_LOOP_INFO_READ:
|
||||
p[poll_server+i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_WRITE:
|
||||
p[poll_server+i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_BLOCK:
|
||||
p[poll_server+i].events |= MHD_POLL_EVENTS_ERR_DISC;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_CLEANUP:
|
||||
timeout = 0; /* clean up "pos" immediately */
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
case MHD_EVENT_LOOP_INFO_READ:
|
||||
p[poll_server + i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_WRITE:
|
||||
p[poll_server + i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_BLOCK:
|
||||
p[poll_server + i].events |= MHD_POLL_EVENTS_ERR_DISC;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_CLEANUP:
|
||||
timeout = 0; /* clean up "pos" immediately */
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
|
||||
for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
|
||||
{
|
||||
urh_to_pollfd (urh,
|
||||
&(p[poll_server+i]));
|
||||
i += 2;
|
||||
}
|
||||
{
|
||||
urh_to_pollfd (urh,
|
||||
&(p[poll_server + i]));
|
||||
i += 2;
|
||||
}
|
||||
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
|
||||
if (0 == poll_server + num_connections)
|
||||
{
|
||||
free (p);
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
if (MHD_sys_poll_ (p,
|
||||
poll_server + num_connections,
|
||||
timeout) < 0)
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
{
|
||||
free (p);
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
if (MHD_sys_poll_(p,
|
||||
poll_server + num_connections,
|
||||
timeout) < 0)
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
{
|
||||
free(p);
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_UNEXPECTED_POLL_ERROR,
|
||||
_("poll failed: %s\n"),
|
||||
MHD_socket_strerr_ (err));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_UNEXPECTED_POLL_ERROR,
|
||||
_ ("poll failed: %s\n"),
|
||||
MHD_socket_strerr_ (err));
|
||||
#endif
|
||||
free(p);
|
||||
return MHD_SC_UNEXPECTED_POLL_ERROR;
|
||||
}
|
||||
free (p);
|
||||
return MHD_SC_UNEXPECTED_POLL_ERROR;
|
||||
}
|
||||
|
||||
/* Reset. New value will be set when connections are processed. */
|
||||
daemon->data_already_pending = false;
|
||||
@@ -281,67 +281,69 @@ MHD_daemon_poll_all_ (struct MHD_Daemon *daemon,
|
||||
|
||||
/* handle shutdown */
|
||||
if (daemon->shutdown)
|
||||
{
|
||||
free(p);
|
||||
return MHD_SC_DAEMON_ALREADY_SHUTDOWN;
|
||||
}
|
||||
{
|
||||
free (p);
|
||||
return MHD_SC_DAEMON_ALREADY_SHUTDOWN;
|
||||
}
|
||||
i = 0;
|
||||
prev = daemon->connections_tail;
|
||||
while (NULL != (pos = prev))
|
||||
{
|
||||
prev = pos->prev;
|
||||
/* first, sanity checks */
|
||||
if (i >= num_connections)
|
||||
break; /* connection list changed somehow, retry later ... */
|
||||
if (p[poll_server+i].fd != pos->socket_fd)
|
||||
continue; /* fd mismatch, something else happened, retry later ... */
|
||||
MHD_connection_call_handlers_ (pos,
|
||||
0 != (p[poll_server+i].revents & POLLIN),
|
||||
0 != (p[poll_server+i].revents & POLLOUT),
|
||||
0 != (p[poll_server+i].revents & MHD_POLL_REVENTS_ERR_DISC));
|
||||
i++;
|
||||
}
|
||||
{
|
||||
prev = pos->prev;
|
||||
/* first, sanity checks */
|
||||
if (i >= num_connections)
|
||||
break; /* connection list changed somehow, retry later ... */
|
||||
if (p[poll_server + i].fd != pos->socket_fd)
|
||||
continue; /* fd mismatch, something else happened, retry later ... */
|
||||
MHD_connection_call_handlers_ (pos,
|
||||
0 != (p[poll_server + i].revents & POLLIN),
|
||||
0 != (p[poll_server + i].revents
|
||||
& POLLOUT),
|
||||
0 != (p[poll_server + i].revents
|
||||
& MHD_POLL_REVENTS_ERR_DISC));
|
||||
i++;
|
||||
}
|
||||
#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
|
||||
for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
|
||||
{
|
||||
if (i >= num_connections)
|
||||
break; /* connection list changed somehow, retry later ... */
|
||||
{
|
||||
if (i >= num_connections)
|
||||
break; /* connection list changed somehow, retry later ... */
|
||||
|
||||
/* Get next connection here as connection can be removed
|
||||
* from 'daemon->urh_head' list. */
|
||||
urhn = urh->prev;
|
||||
/* Check for fd mismatch. FIXME: required for safety? */
|
||||
if ((p[poll_server+i].fd != urh->connection->socket_fd) ||
|
||||
(p[poll_server+i+1].fd != urh->mhd.socket))
|
||||
break;
|
||||
urh_from_pollfd (urh,
|
||||
&p[poll_server+i]);
|
||||
i += 2;
|
||||
MHD_upgrade_response_handle_process_ (urh);
|
||||
/* Finished forwarding? */
|
||||
if ( (0 == urh->in_buffer_size) &&
|
||||
(0 == urh->out_buffer_size) &&
|
||||
(0 == urh->in_buffer_used) &&
|
||||
(0 == urh->out_buffer_used) )
|
||||
{
|
||||
/* MHD_connection_finish_forward_() will remove connection from
|
||||
* 'daemon->urh_head' list. */
|
||||
MHD_connection_finish_forward_ (urh->connection);
|
||||
urh->clean_ready = true;
|
||||
/* If 'urh->was_closed' already was set to true, connection will be
|
||||
* moved immediately to cleanup list. Otherwise connection
|
||||
* will stay in suspended list until 'urh' will be marked
|
||||
* with 'was_closed' by application. */
|
||||
MHD_request_resume (&urh->connection->request);
|
||||
}
|
||||
/* Get next connection here as connection can be removed
|
||||
* from 'daemon->urh_head' list. */
|
||||
urhn = urh->prev;
|
||||
/* Check for fd mismatch. FIXME: required for safety? */
|
||||
if ((p[poll_server + i].fd != urh->connection->socket_fd) ||
|
||||
(p[poll_server + i + 1].fd != urh->mhd.socket))
|
||||
break;
|
||||
urh_from_pollfd (urh,
|
||||
&p[poll_server + i]);
|
||||
i += 2;
|
||||
MHD_upgrade_response_handle_process_ (urh);
|
||||
/* Finished forwarding? */
|
||||
if ( (0 == urh->in_buffer_size) &&
|
||||
(0 == urh->out_buffer_size) &&
|
||||
(0 == urh->in_buffer_used) &&
|
||||
(0 == urh->out_buffer_used) )
|
||||
{
|
||||
/* MHD_connection_finish_forward_() will remove connection from
|
||||
* 'daemon->urh_head' list. */
|
||||
MHD_connection_finish_forward_ (urh->connection);
|
||||
urh->clean_ready = true;
|
||||
/* If 'urh->was_closed' already was set to true, connection will be
|
||||
* moved immediately to cleanup list. Otherwise connection
|
||||
* will stay in suspended list until 'urh' will be marked
|
||||
* with 'was_closed' by application. */
|
||||
MHD_request_resume (&urh->connection->request);
|
||||
}
|
||||
}
|
||||
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
|
||||
/* handle 'listen' FD */
|
||||
if ( (-1 != poll_listen) &&
|
||||
(0 != (p[poll_listen].revents & POLLIN)) )
|
||||
(0 != (p[poll_listen].revents & POLLIN)) )
|
||||
(void) MHD_accept_connection_ (daemon);
|
||||
|
||||
free(p);
|
||||
free (p);
|
||||
}
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
@@ -356,7 +358,7 @@ MHD_daemon_poll_all_ (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_poll_listen_socket_ (struct MHD_Daemon *daemon,
|
||||
bool may_block)
|
||||
bool may_block)
|
||||
{
|
||||
struct pollfd p[2];
|
||||
int timeout;
|
||||
@@ -374,21 +376,21 @@ MHD_daemon_poll_listen_socket_ (struct MHD_Daemon *daemon,
|
||||
if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_socket)) &&
|
||||
(! daemon->was_quiesced) )
|
||||
|
||||
{
|
||||
p[poll_count].fd = ls;
|
||||
p[poll_count].events = POLLIN;
|
||||
p[poll_count].revents = 0;
|
||||
poll_listen = poll_count;
|
||||
poll_count++;
|
||||
}
|
||||
if (MHD_ITC_IS_VALID_(daemon->itc))
|
||||
{
|
||||
p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
|
||||
p[poll_count].events = POLLIN;
|
||||
p[poll_count].revents = 0;
|
||||
poll_itc_idx = poll_count;
|
||||
poll_count++;
|
||||
}
|
||||
{
|
||||
p[poll_count].fd = ls;
|
||||
p[poll_count].events = POLLIN;
|
||||
p[poll_count].revents = 0;
|
||||
poll_listen = poll_count;
|
||||
poll_count++;
|
||||
}
|
||||
if (MHD_ITC_IS_VALID_ (daemon->itc))
|
||||
{
|
||||
p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
|
||||
p[poll_count].events = POLLIN;
|
||||
p[poll_count].revents = 0;
|
||||
poll_itc_idx = poll_count;
|
||||
poll_count++;
|
||||
}
|
||||
|
||||
if (! daemon->disallow_suspend_resume)
|
||||
(void) MHD_resume_suspended_connections_ (daemon);
|
||||
@@ -399,22 +401,22 @@ MHD_daemon_poll_listen_socket_ (struct MHD_Daemon *daemon,
|
||||
timeout = -1;
|
||||
if (0 == poll_count)
|
||||
return MHD_SC_OK;
|
||||
if (MHD_sys_poll_(p,
|
||||
poll_count,
|
||||
timeout) < 0)
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
if (MHD_sys_poll_ (p,
|
||||
poll_count,
|
||||
timeout) < 0)
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
return MHD_SC_OK;
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
return MHD_SC_OK;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_UNEXPECTED_POLL_ERROR,
|
||||
_("poll failed: %s\n"),
|
||||
MHD_socket_strerr_ (err));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_UNEXPECTED_POLL_ERROR,
|
||||
_ ("poll failed: %s\n"),
|
||||
MHD_socket_strerr_ (err));
|
||||
#endif
|
||||
return MHD_SC_UNEXPECTED_POLL_ERROR;
|
||||
}
|
||||
return MHD_SC_UNEXPECTED_POLL_ERROR;
|
||||
}
|
||||
if ( (-1 != poll_itc_idx) &&
|
||||
(0 != (p[poll_itc_idx].revents & POLLIN)) )
|
||||
MHD_itc_clear_ (daemon->itc);
|
||||
@@ -439,16 +441,16 @@ MHD_daemon_poll_listen_socket_ (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_poll_ (struct MHD_Daemon *daemon,
|
||||
bool may_block)
|
||||
bool may_block)
|
||||
{
|
||||
#ifdef HAVE_POLL
|
||||
if (daemon->shutdown)
|
||||
return MHD_SC_DAEMON_ALREADY_SHUTDOWN;
|
||||
if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
|
||||
return MHD_daemon_poll_all_ (daemon,
|
||||
may_block);
|
||||
may_block);
|
||||
return MHD_daemon_poll_listen_socket_ (daemon,
|
||||
may_block);
|
||||
may_block);
|
||||
#else
|
||||
/* This code should be dead, as we should have checked
|
||||
this earlier... */
|
||||
@@ -472,47 +474,47 @@ MHD_daemon_upgrade_connection_with_poll_ (struct MHD_Connection *con)
|
||||
struct pollfd p[2];
|
||||
|
||||
memset (p,
|
||||
0,
|
||||
sizeof (p));
|
||||
0,
|
||||
sizeof (p));
|
||||
p[0].fd = urh->connection->socket_fd;
|
||||
p[1].fd = urh->mhd.socket;
|
||||
|
||||
while ( (0 != urh->in_buffer_size) ||
|
||||
(0 != urh->out_buffer_size) ||
|
||||
(0 != urh->in_buffer_used) ||
|
||||
(0 != urh->out_buffer_used) )
|
||||
(0 != urh->out_buffer_size) ||
|
||||
(0 != urh->in_buffer_used) ||
|
||||
(0 != urh->out_buffer_used) )
|
||||
{
|
||||
int timeout;
|
||||
|
||||
urh_update_pollfd (urh,
|
||||
p);
|
||||
|
||||
if ( (con->tls_read_ready) &&
|
||||
(urh->in_buffer_used < urh->in_buffer_size))
|
||||
timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
|
||||
else
|
||||
timeout = -1;
|
||||
|
||||
if (MHD_sys_poll_ (p,
|
||||
2,
|
||||
timeout) < 0)
|
||||
{
|
||||
int timeout;
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
|
||||
urh_update_pollfd (urh,
|
||||
p);
|
||||
|
||||
if ( (con->tls_read_ready) &&
|
||||
(urh->in_buffer_used < urh->in_buffer_size))
|
||||
timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
|
||||
else
|
||||
timeout = -1;
|
||||
|
||||
if (MHD_sys_poll_ (p,
|
||||
2,
|
||||
timeout) < 0)
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
continue;
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
continue;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_UNEXPECTED_POLL_ERROR,
|
||||
_("Error during poll: `%s'\n"),
|
||||
MHD_socket_strerr_ (err));
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_UNEXPECTED_POLL_ERROR,
|
||||
_ ("Error during poll: `%s'\n"),
|
||||
MHD_socket_strerr_ (err));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
urh_from_pollfd (urh,
|
||||
p);
|
||||
MHD_upgrade_response_handle_process_ (urh);
|
||||
break;
|
||||
}
|
||||
urh_from_pollfd (urh,
|
||||
p);
|
||||
MHD_upgrade_response_handle_process_ (urh);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_poll_all_ (struct MHD_Daemon *daemon,
|
||||
bool may_block)
|
||||
MHD_NONNULL(1);
|
||||
bool may_block)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -50,8 +50,8 @@ MHD_daemon_poll_all_ (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_poll_listen_socket_ (struct MHD_Daemon *daemon,
|
||||
bool may_block)
|
||||
MHD_NONNULL (1);
|
||||
bool may_block)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -63,8 +63,8 @@ MHD_daemon_poll_listen_socket_ (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_poll_ (struct MHD_Daemon *daemon,
|
||||
bool may_block)
|
||||
MHD_NONNULL (1);
|
||||
bool may_block)
|
||||
MHD_NONNULL (1);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ MHD_daemon_poll_ (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_upgrade_connection_with_poll_ (struct MHD_Connection *con)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
+53
-52
@@ -54,75 +54,76 @@ MHD_daemon_quiesce (struct MHD_Daemon *daemon)
|
||||
return MHD_INVALID_SOCKET;
|
||||
if ( (daemon->disable_itc) &&
|
||||
(MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode) )
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_SYSCALL_QUIESCE_REQUIRES_ITC,
|
||||
"Using MHD_quiesce_daemon in this mode requires ITC\n");
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_SYSCALL_QUIESCE_REQUIRES_ITC,
|
||||
"Using MHD_quiesce_daemon in this mode requires ITC\n");
|
||||
#endif
|
||||
return MHD_INVALID_SOCKET;
|
||||
}
|
||||
return MHD_INVALID_SOCKET;
|
||||
}
|
||||
|
||||
if (NULL != daemon->worker_pool)
|
||||
{
|
||||
unsigned int i;
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < daemon->worker_pool_size; i++)
|
||||
{
|
||||
struct MHD_Daemon *worker = &daemon->worker_pool[i];
|
||||
|
||||
worker->was_quiesced = true;
|
||||
#ifdef EPOLL_SUPPORT
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
|
||||
(-1 != worker->epoll_fd) &&
|
||||
(worker->listen_socket_in_epoll) )
|
||||
{
|
||||
if (0 != epoll_ctl (worker->epoll_fd,
|
||||
EPOLL_CTL_DEL,
|
||||
listen_socket,
|
||||
NULL))
|
||||
MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
|
||||
worker->listen_socket_in_epoll = false;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (MHD_ITC_IS_VALID_(worker->itc))
|
||||
{
|
||||
if (! MHD_itc_activate_ (worker->itc,
|
||||
"q"))
|
||||
MHD_PANIC (_("Failed to signal quiesce via inter-thread communication channel"));
|
||||
}
|
||||
}
|
||||
daemon->was_quiesced = true;
|
||||
for (i = 0; i < daemon->worker_pool_size; i++)
|
||||
{
|
||||
struct MHD_Daemon *worker = &daemon->worker_pool[i];
|
||||
|
||||
worker->was_quiesced = true;
|
||||
#ifdef EPOLL_SUPPORT
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
|
||||
(-1 != daemon->epoll_fd) &&
|
||||
(daemon->listen_socket_in_epoll) )
|
||||
{
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_DEL,
|
||||
listen_socket,
|
||||
NULL))
|
||||
MHD_PANIC ("Failed to remove listen FD from epoll set\n");
|
||||
daemon->listen_socket_in_epoll = false;
|
||||
}
|
||||
(-1 != worker->epoll_fd) &&
|
||||
(worker->listen_socket_in_epoll) )
|
||||
{
|
||||
if (0 != epoll_ctl (worker->epoll_fd,
|
||||
EPOLL_CTL_DEL,
|
||||
listen_socket,
|
||||
NULL))
|
||||
MHD_PANIC (_ ("Failed to remove listen FD from epoll set\n"));
|
||||
worker->listen_socket_in_epoll = false;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (MHD_ITC_IS_VALID_ (worker->itc))
|
||||
{
|
||||
if (! MHD_itc_activate_ (worker->itc,
|
||||
"q"))
|
||||
MHD_PANIC (_ (
|
||||
"Failed to signal quiesce via inter-thread communication channel"));
|
||||
}
|
||||
}
|
||||
|
||||
if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
|
||||
daemon->was_quiesced = true;
|
||||
#ifdef EPOLL_SUPPORT
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
|
||||
(-1 != daemon->epoll_fd) &&
|
||||
(daemon->listen_socket_in_epoll) )
|
||||
{
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_DEL,
|
||||
listen_socket,
|
||||
NULL))
|
||||
MHD_PANIC ("Failed to remove listen FD from epoll set\n");
|
||||
daemon->listen_socket_in_epoll = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
|
||||
(! MHD_itc_activate_ (daemon->itc,
|
||||
"q")) )
|
||||
MHD_PANIC (_("Failed to signal quiesce via inter-thread communication channel"));
|
||||
"q")) )
|
||||
MHD_PANIC (_ (
|
||||
"Failed to signal quiesce via inter-thread communication channel"));
|
||||
|
||||
/* FIXME: we might want some bi-directional communication here
|
||||
(in both the thread-pool and single-thread case!)
|
||||
(in both the thread-pool and single-thread case!)
|
||||
to be sure that the threads have stopped using the listen
|
||||
socket, otherwise there is still the possibility of a race
|
||||
between a thread accept()ing and the caller closing and
|
||||
re-binding the socket. */
|
||||
|
||||
|
||||
return listen_socket;
|
||||
}
|
||||
|
||||
/* end of daemon_quiesce.c */
|
||||
|
||||
|
||||
+18
-18
@@ -57,26 +57,26 @@ MHD_daemon_run (struct MHD_Daemon *daemon)
|
||||
if (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode)
|
||||
return MHD_SC_CONFIGURATION_MISMATCH_FOR_RUN_EXTERNAL;
|
||||
switch (daemon->event_loop_syscall)
|
||||
{
|
||||
case MHD_ELS_POLL:
|
||||
sc = MHD_daemon_poll_ (daemon,
|
||||
MHD_NO);
|
||||
MHD_connection_cleanup_ (daemon);
|
||||
return sc;
|
||||
{
|
||||
case MHD_ELS_POLL:
|
||||
sc = MHD_daemon_poll_ (daemon,
|
||||
MHD_NO);
|
||||
MHD_connection_cleanup_ (daemon);
|
||||
return sc;
|
||||
#ifdef EPOLL_SUPPORT
|
||||
case MHD_ELS_EPOLL:
|
||||
sc = MHD_daemon_epoll_ (daemon,
|
||||
MHD_NO);
|
||||
MHD_connection_cleanup_ (daemon);
|
||||
return sc;
|
||||
case MHD_ELS_EPOLL:
|
||||
sc = MHD_daemon_epoll_ (daemon,
|
||||
MHD_NO);
|
||||
MHD_connection_cleanup_ (daemon);
|
||||
return sc;
|
||||
#endif
|
||||
case MHD_ELS_SELECT:
|
||||
return MHD_daemon_select_ (daemon,
|
||||
MHD_NO);
|
||||
/* MHD_select does MHD_connection_cleanup_ already */
|
||||
default:
|
||||
return MHD_SC_CONFIGURATION_UNEXPECTED_ELS;
|
||||
}
|
||||
case MHD_ELS_SELECT:
|
||||
return MHD_daemon_select_ (daemon,
|
||||
MHD_NO);
|
||||
/* MHD_select does MHD_connection_cleanup_ already */
|
||||
default:
|
||||
return MHD_SC_CONFIGURATION_UNEXPECTED_ELS;
|
||||
}
|
||||
}
|
||||
|
||||
/* end of daemon_run.c */
|
||||
|
||||
+356
-355
@@ -66,17 +66,17 @@
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_get_fdset (struct MHD_Daemon *daemon,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *except_fd_set,
|
||||
MHD_socket *max_fd)
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *except_fd_set,
|
||||
MHD_socket *max_fd)
|
||||
{
|
||||
return MHD_daemon_get_fdset2 (daemon,
|
||||
read_fd_set,
|
||||
write_fd_set,
|
||||
except_fd_set,
|
||||
max_fd,
|
||||
_MHD_SYS_DEFAULT_FD_SETSIZE);
|
||||
read_fd_set,
|
||||
write_fd_set,
|
||||
except_fd_set,
|
||||
max_fd,
|
||||
_MHD_SYS_DEFAULT_FD_SETSIZE);
|
||||
}
|
||||
|
||||
|
||||
@@ -108,55 +108,55 @@ urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
|
||||
/* Do not add to 'es' only if socket is closed
|
||||
* or not used anymore. */
|
||||
if (MHD_INVALID_SOCKET != conn_sckt)
|
||||
{
|
||||
if ( (urh->in_buffer_used < urh->in_buffer_size) &&
|
||||
(! MHD_add_to_fd_set_ (conn_sckt,
|
||||
rs,
|
||||
max_fd,
|
||||
fd_setsize)) )
|
||||
res = false;
|
||||
if ( (0 != urh->out_buffer_used) &&
|
||||
(! MHD_add_to_fd_set_ (conn_sckt,
|
||||
ws,
|
||||
max_fd,
|
||||
fd_setsize)) )
|
||||
res = false;
|
||||
/* Do not monitor again for errors if error was detected before as
|
||||
* error state is remembered. */
|
||||
if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
|
||||
((0 != urh->in_buffer_size) ||
|
||||
(0 != urh->out_buffer_size) ||
|
||||
(0 != urh->out_buffer_used)))
|
||||
MHD_add_to_fd_set_ (conn_sckt,
|
||||
es,
|
||||
max_fd,
|
||||
fd_setsize);
|
||||
}
|
||||
{
|
||||
if ( (urh->in_buffer_used < urh->in_buffer_size) &&
|
||||
(! MHD_add_to_fd_set_ (conn_sckt,
|
||||
rs,
|
||||
max_fd,
|
||||
fd_setsize)) )
|
||||
res = false;
|
||||
if ( (0 != urh->out_buffer_used) &&
|
||||
(! MHD_add_to_fd_set_ (conn_sckt,
|
||||
ws,
|
||||
max_fd,
|
||||
fd_setsize)) )
|
||||
res = false;
|
||||
/* Do not monitor again for errors if error was detected before as
|
||||
* error state is remembered. */
|
||||
if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
|
||||
((0 != urh->in_buffer_size) ||
|
||||
(0 != urh->out_buffer_size) ||
|
||||
(0 != urh->out_buffer_used)))
|
||||
MHD_add_to_fd_set_ (conn_sckt,
|
||||
es,
|
||||
max_fd,
|
||||
fd_setsize);
|
||||
}
|
||||
if (MHD_INVALID_SOCKET != mhd_sckt)
|
||||
{
|
||||
if ( (urh->out_buffer_used < urh->out_buffer_size) &&
|
||||
(! MHD_add_to_fd_set_ (mhd_sckt,
|
||||
rs,
|
||||
max_fd,
|
||||
fd_setsize)) )
|
||||
res = false;
|
||||
if ( (0 != urh->in_buffer_used) &&
|
||||
(! MHD_add_to_fd_set_ (mhd_sckt,
|
||||
ws,
|
||||
max_fd,
|
||||
fd_setsize)) )
|
||||
res = false;
|
||||
/* Do not monitor again for errors if error was detected before as
|
||||
* error state is remembered. */
|
||||
if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
|
||||
((0 != urh->out_buffer_size) ||
|
||||
(0 != urh->in_buffer_size) ||
|
||||
(0 != urh->in_buffer_used)))
|
||||
MHD_add_to_fd_set_ (mhd_sckt,
|
||||
es,
|
||||
max_fd,
|
||||
fd_setsize);
|
||||
}
|
||||
{
|
||||
if ( (urh->out_buffer_used < urh->out_buffer_size) &&
|
||||
(! MHD_add_to_fd_set_ (mhd_sckt,
|
||||
rs,
|
||||
max_fd,
|
||||
fd_setsize)) )
|
||||
res = false;
|
||||
if ( (0 != urh->in_buffer_used) &&
|
||||
(! MHD_add_to_fd_set_ (mhd_sckt,
|
||||
ws,
|
||||
max_fd,
|
||||
fd_setsize)) )
|
||||
res = false;
|
||||
/* Do not monitor again for errors if error was detected before as
|
||||
* error state is remembered. */
|
||||
if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
|
||||
((0 != urh->out_buffer_size) ||
|
||||
(0 != urh->in_buffer_size) ||
|
||||
(0 != urh->in_buffer_used)))
|
||||
MHD_add_to_fd_set_ (mhd_sckt,
|
||||
es,
|
||||
max_fd,
|
||||
fd_setsize);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -207,77 +207,77 @@ internal_get_fdset2 (struct MHD_Daemon *daemon,
|
||||
* or INFO_WRITE sockets will not fit 'except_fd_set'. */
|
||||
/* Start from oldest connections. Make sense for W32 FDSETs. */
|
||||
for (pos = daemon->connections_tail; NULL != pos; pos = posn)
|
||||
{
|
||||
posn = pos->prev;
|
||||
{
|
||||
posn = pos->prev;
|
||||
|
||||
switch (pos->request.event_loop_info)
|
||||
{
|
||||
case MHD_EVENT_LOOP_INFO_READ:
|
||||
if (! MHD_add_to_fd_set_ (pos->socket_fd,
|
||||
read_fd_set,
|
||||
max_fd,
|
||||
fd_setsize))
|
||||
result = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
switch (pos->request.event_loop_info)
|
||||
{
|
||||
case MHD_EVENT_LOOP_INFO_READ:
|
||||
if (! MHD_add_to_fd_set_ (pos->socket_fd,
|
||||
read_fd_set,
|
||||
max_fd,
|
||||
fd_setsize))
|
||||
result = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
#ifdef MHD_POSIX_SOCKETS
|
||||
MHD_add_to_fd_set_ (pos->socket_fd,
|
||||
except_fd_set,
|
||||
max_fd,
|
||||
fd_setsize);
|
||||
MHD_add_to_fd_set_ (pos->socket_fd,
|
||||
except_fd_set,
|
||||
max_fd,
|
||||
fd_setsize);
|
||||
#endif /* MHD_POSIX_SOCKETS */
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_WRITE:
|
||||
if (! MHD_add_to_fd_set_ (pos->socket_fd,
|
||||
write_fd_set,
|
||||
max_fd,
|
||||
fd_setsize))
|
||||
result = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_WRITE:
|
||||
if (! MHD_add_to_fd_set_ (pos->socket_fd,
|
||||
write_fd_set,
|
||||
max_fd,
|
||||
fd_setsize))
|
||||
result = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
#ifdef MHD_POSIX_SOCKETS
|
||||
MHD_add_to_fd_set_ (pos->socket_fd,
|
||||
except_fd_set,
|
||||
max_fd,
|
||||
fd_setsize);
|
||||
MHD_add_to_fd_set_ (pos->socket_fd,
|
||||
except_fd_set,
|
||||
max_fd,
|
||||
fd_setsize);
|
||||
#endif /* MHD_POSIX_SOCKETS */
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_BLOCK:
|
||||
if ( (NULL == except_fd_set) ||
|
||||
! MHD_add_to_fd_set_ (pos->socket_fd,
|
||||
except_fd_set,
|
||||
max_fd,
|
||||
fd_setsize))
|
||||
result = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_CLEANUP:
|
||||
/* this should never happen */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_BLOCK:
|
||||
if ( (NULL == except_fd_set) ||
|
||||
! MHD_add_to_fd_set_ (pos->socket_fd,
|
||||
except_fd_set,
|
||||
max_fd,
|
||||
fd_setsize))
|
||||
result = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
break;
|
||||
case MHD_EVENT_LOOP_INFO_CLEANUP:
|
||||
/* this should never happen */
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef MHD_WINSOCK_SOCKETS
|
||||
/* W32 use limited array for fd_set so add INFO_READ/INFO_WRITE sockets
|
||||
* only after INFO_BLOCK sockets to ensure that INFO_BLOCK sockets will
|
||||
* not be pushed out. */
|
||||
for (pos = daemon->connections_tail; NULL != pos; pos = posn)
|
||||
{
|
||||
posn = pos->prev;
|
||||
MHD_add_to_fd_set_ (pos->socket_fd,
|
||||
except_fd_set,
|
||||
max_fd,
|
||||
fd_setsize);
|
||||
}
|
||||
{
|
||||
posn = pos->prev;
|
||||
MHD_add_to_fd_set_ (pos->socket_fd,
|
||||
except_fd_set,
|
||||
max_fd,
|
||||
fd_setsize);
|
||||
}
|
||||
#endif /* MHD_WINSOCK_SOCKETS */
|
||||
#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
|
||||
{
|
||||
struct MHD_UpgradeResponseHandle *urh;
|
||||
|
||||
for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
|
||||
{
|
||||
if (! urh_to_fdset (urh,
|
||||
read_fd_set,
|
||||
write_fd_set,
|
||||
except_fd_set,
|
||||
max_fd,
|
||||
fd_setsize))
|
||||
result = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
}
|
||||
{
|
||||
if (! urh_to_fdset (urh,
|
||||
read_fd_set,
|
||||
write_fd_set,
|
||||
except_fd_set,
|
||||
max_fd,
|
||||
fd_setsize))
|
||||
result = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
@@ -313,11 +313,11 @@ internal_get_fdset2 (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_get_fdset2 (struct MHD_Daemon *daemon,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *except_fd_set,
|
||||
MHD_socket *max_fd,
|
||||
unsigned int fd_setsize)
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *except_fd_set,
|
||||
MHD_socket *max_fd,
|
||||
unsigned int fd_setsize)
|
||||
{
|
||||
if ( (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode) ||
|
||||
(MHD_ELS_POLL == daemon->event_loop_syscall) )
|
||||
@@ -325,28 +325,28 @@ MHD_daemon_get_fdset2 (struct MHD_Daemon *daemon,
|
||||
|
||||
#ifdef EPOLL_SUPPORT
|
||||
if (MHD_ELS_EPOLL == daemon->event_loop_syscall)
|
||||
{
|
||||
if (daemon->shutdown)
|
||||
return MHD_SC_DAEMON_ALREADY_SHUTDOWN;
|
||||
{
|
||||
if (daemon->shutdown)
|
||||
return MHD_SC_DAEMON_ALREADY_SHUTDOWN;
|
||||
|
||||
/* we're in epoll mode, use the epoll FD as a stand-in for
|
||||
the entire event set */
|
||||
/* we're in epoll mode, use the epoll FD as a stand-in for
|
||||
the entire event set */
|
||||
|
||||
return MHD_add_to_fd_set_ (daemon->epoll_fd,
|
||||
read_fd_set,
|
||||
max_fd,
|
||||
fd_setsize)
|
||||
? MHD_SC_OK
|
||||
: MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
}
|
||||
return MHD_add_to_fd_set_ (daemon->epoll_fd,
|
||||
read_fd_set,
|
||||
max_fd,
|
||||
fd_setsize)
|
||||
? MHD_SC_OK
|
||||
: MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return internal_get_fdset2 (daemon,
|
||||
read_fd_set,
|
||||
read_fd_set,
|
||||
write_fd_set,
|
||||
except_fd_set,
|
||||
except_fd_set,
|
||||
max_fd,
|
||||
fd_setsize);
|
||||
fd_setsize);
|
||||
}
|
||||
|
||||
|
||||
@@ -374,23 +374,23 @@ urh_from_fdset (struct MHD_UpgradeResponseHandle *urh,
|
||||
urh->mhd.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
|
||||
|
||||
if (MHD_INVALID_SOCKET != conn_sckt)
|
||||
{
|
||||
if (FD_ISSET (conn_sckt, rs))
|
||||
urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
|
||||
if (FD_ISSET (conn_sckt, ws))
|
||||
urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
|
||||
if (FD_ISSET (conn_sckt, es))
|
||||
urh->app.celi |= MHD_EPOLL_STATE_ERROR;
|
||||
}
|
||||
{
|
||||
if (FD_ISSET (conn_sckt, rs))
|
||||
urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
|
||||
if (FD_ISSET (conn_sckt, ws))
|
||||
urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
|
||||
if (FD_ISSET (conn_sckt, es))
|
||||
urh->app.celi |= MHD_EPOLL_STATE_ERROR;
|
||||
}
|
||||
if ((MHD_INVALID_SOCKET != mhd_sckt))
|
||||
{
|
||||
if (FD_ISSET (mhd_sckt, rs))
|
||||
urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
|
||||
if (FD_ISSET (mhd_sckt, ws))
|
||||
urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
|
||||
if (FD_ISSET (mhd_sckt, es))
|
||||
urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
|
||||
}
|
||||
{
|
||||
if (FD_ISSET (mhd_sckt, rs))
|
||||
urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
|
||||
if (FD_ISSET (mhd_sckt, ws))
|
||||
urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
|
||||
if (FD_ISSET (mhd_sckt, es))
|
||||
urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -425,7 +425,7 @@ internal_run_from_select (struct MHD_Daemon *daemon,
|
||||
/* Clear ITC to avoid spinning select */
|
||||
/* Do it before any other processing so new signals
|
||||
will trigger select again and will be processed */
|
||||
if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
|
||||
if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
|
||||
(FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
|
||||
read_fd_set)) )
|
||||
MHD_itc_clear_ (daemon->itc);
|
||||
@@ -438,49 +438,49 @@ internal_run_from_select (struct MHD_Daemon *daemon,
|
||||
(void) MHD_accept_connection_ (daemon);
|
||||
|
||||
if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
|
||||
{
|
||||
/* do not have a thread per connection, process all connections now */
|
||||
prev = daemon->connections_tail;
|
||||
while (NULL != (pos = prev))
|
||||
{
|
||||
/* do not have a thread per connection, process all connections now */
|
||||
prev = daemon->connections_tail;
|
||||
while (NULL != (pos = prev))
|
||||
{
|
||||
prev = pos->prev;
|
||||
ds = pos->socket_fd;
|
||||
if (MHD_INVALID_SOCKET == ds)
|
||||
continue;
|
||||
MHD_connection_call_handlers_ (pos,
|
||||
FD_ISSET (ds,
|
||||
read_fd_set),
|
||||
FD_ISSET (ds,
|
||||
write_fd_set),
|
||||
FD_ISSET (ds,
|
||||
except_fd_set));
|
||||
}
|
||||
prev = pos->prev;
|
||||
ds = pos->socket_fd;
|
||||
if (MHD_INVALID_SOCKET == ds)
|
||||
continue;
|
||||
MHD_connection_call_handlers_ (pos,
|
||||
FD_ISSET (ds,
|
||||
read_fd_set),
|
||||
FD_ISSET (ds,
|
||||
write_fd_set),
|
||||
FD_ISSET (ds,
|
||||
except_fd_set));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
|
||||
/* handle upgraded HTTPS connections */
|
||||
for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
|
||||
{
|
||||
urhn = urh->prev;
|
||||
/* update urh state based on select() output */
|
||||
urh_from_fdset (urh,
|
||||
read_fd_set,
|
||||
write_fd_set,
|
||||
except_fd_set);
|
||||
/* call generic forwarding function for passing data */
|
||||
MHD_upgrade_response_handle_process_ (urh);
|
||||
/* Finished forwarding? */
|
||||
if ( (0 == urh->in_buffer_size) &&
|
||||
(0 == urh->out_buffer_size) &&
|
||||
(0 == urh->in_buffer_used) &&
|
||||
(0 == urh->out_buffer_used) )
|
||||
{
|
||||
urhn = urh->prev;
|
||||
/* update urh state based on select() output */
|
||||
urh_from_fdset (urh,
|
||||
read_fd_set,
|
||||
write_fd_set,
|
||||
except_fd_set);
|
||||
/* call generic forwarding function for passing data */
|
||||
MHD_upgrade_response_handle_process_ (urh);
|
||||
/* Finished forwarding? */
|
||||
if ( (0 == urh->in_buffer_size) &&
|
||||
(0 == urh->out_buffer_size) &&
|
||||
(0 == urh->in_buffer_used) &&
|
||||
(0 == urh->out_buffer_used) )
|
||||
{
|
||||
MHD_connection_finish_forward_ (urh->connection);
|
||||
urh->clean_ready = true;
|
||||
/* Resuming will move connection to cleanup list. */
|
||||
MHD_request_resume (&urh->connection->request);
|
||||
}
|
||||
MHD_connection_finish_forward_ (urh->connection);
|
||||
urh->clean_ready = true;
|
||||
/* Resuming will move connection to cleanup list. */
|
||||
MHD_request_resume (&urh->connection->request);
|
||||
}
|
||||
}
|
||||
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
|
||||
MHD_connection_cleanup_ (daemon);
|
||||
return MHD_SC_OK;
|
||||
@@ -500,80 +500,80 @@ MHD_daemon_upgrade_connection_with_select_ (struct MHD_Connection *con)
|
||||
struct MHD_UpgradeResponseHandle *urh = con->request.urh;
|
||||
|
||||
while ( (0 != urh->in_buffer_size) ||
|
||||
(0 != urh->out_buffer_size) ||
|
||||
(0 != urh->in_buffer_used) ||
|
||||
(0 != urh->out_buffer_used) )
|
||||
(0 != urh->out_buffer_size) ||
|
||||
(0 != urh->in_buffer_used) ||
|
||||
(0 != urh->out_buffer_used) )
|
||||
{
|
||||
/* use select */
|
||||
fd_set rs;
|
||||
fd_set ws;
|
||||
fd_set es;
|
||||
MHD_socket max_fd;
|
||||
int num_ready;
|
||||
bool result;
|
||||
|
||||
FD_ZERO (&rs);
|
||||
FD_ZERO (&ws);
|
||||
FD_ZERO (&es);
|
||||
max_fd = MHD_INVALID_SOCKET;
|
||||
result = urh_to_fdset (urh,
|
||||
&rs,
|
||||
&ws,
|
||||
&es,
|
||||
&max_fd,
|
||||
FD_SETSIZE);
|
||||
if (! result)
|
||||
{
|
||||
/* use select */
|
||||
fd_set rs;
|
||||
fd_set ws;
|
||||
fd_set es;
|
||||
MHD_socket max_fd;
|
||||
int num_ready;
|
||||
bool result;
|
||||
|
||||
FD_ZERO (&rs);
|
||||
FD_ZERO (&ws);
|
||||
FD_ZERO (&es);
|
||||
max_fd = MHD_INVALID_SOCKET;
|
||||
result = urh_to_fdset (urh,
|
||||
&rs,
|
||||
&ws,
|
||||
&es,
|
||||
&max_fd,
|
||||
FD_SETSIZE);
|
||||
if (! result)
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
|
||||
_("Error preparing select\n"));
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
|
||||
_ ("Error preparing select\n"));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
/* FIXME: does this check really needed? */
|
||||
if (MHD_INVALID_SOCKET != max_fd)
|
||||
{
|
||||
struct timeval* tvp;
|
||||
struct timeval tv;
|
||||
if ( (con->tls_read_ready) &&
|
||||
(urh->in_buffer_used < urh->in_buffer_size))
|
||||
{ /* No need to wait if incoming data is already pending in TLS buffers. */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
tvp = &tv;
|
||||
}
|
||||
else
|
||||
tvp = NULL;
|
||||
num_ready = MHD_SYS_select_ (max_fd + 1,
|
||||
&rs,
|
||||
&ws,
|
||||
&es,
|
||||
tvp);
|
||||
}
|
||||
else
|
||||
num_ready = 0;
|
||||
if (num_ready < 0)
|
||||
{
|
||||
const int err = MHD_socket_get_error_();
|
||||
|
||||
if (MHD_SCKT_ERR_IS_EINTR_(err))
|
||||
continue;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_UNEXPECTED_SELECT_ERROR,
|
||||
_("Error during select (%d): `%s'\n"),
|
||||
err,
|
||||
MHD_socket_strerr_ (err));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
urh_from_fdset (urh,
|
||||
&rs,
|
||||
&ws,
|
||||
&es);
|
||||
MHD_upgrade_response_handle_process_ (urh);
|
||||
break;
|
||||
}
|
||||
/* FIXME: does this check really needed? */
|
||||
if (MHD_INVALID_SOCKET != max_fd)
|
||||
{
|
||||
struct timeval*tvp;
|
||||
struct timeval tv;
|
||||
if ( (con->tls_read_ready) &&
|
||||
(urh->in_buffer_used < urh->in_buffer_size))
|
||||
{ /* No need to wait if incoming data is already pending in TLS buffers. */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
tvp = &tv;
|
||||
}
|
||||
else
|
||||
tvp = NULL;
|
||||
num_ready = MHD_SYS_select_ (max_fd + 1,
|
||||
&rs,
|
||||
&ws,
|
||||
&es,
|
||||
tvp);
|
||||
}
|
||||
else
|
||||
num_ready = 0;
|
||||
if (num_ready < 0)
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
continue;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (con->daemon,
|
||||
MHD_SC_UNEXPECTED_SELECT_ERROR,
|
||||
_ ("Error during select (%d): `%s'\n"),
|
||||
err,
|
||||
MHD_socket_strerr_ (err));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
urh_from_fdset (urh,
|
||||
&rs,
|
||||
&ws,
|
||||
&es);
|
||||
MHD_upgrade_response_handle_process_ (urh);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -602,37 +602,37 @@ MHD_daemon_upgrade_connection_with_select_ (struct MHD_Connection *con)
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_run_from_select (struct MHD_Daemon *daemon,
|
||||
const fd_set *read_fd_set,
|
||||
const fd_set *read_fd_set,
|
||||
|
||||
|
||||
const fd_set *write_fd_set,
|
||||
const fd_set *except_fd_set)
|
||||
const fd_set *write_fd_set,
|
||||
const fd_set *except_fd_set)
|
||||
{
|
||||
if ( (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode) ||
|
||||
(MHD_ELS_POLL == daemon->event_loop_syscall) )
|
||||
return MHD_SC_CONFIGURATION_MISSMATCH_FOR_RUN_SELECT;
|
||||
if (MHD_ELS_EPOLL == daemon->event_loop_syscall)
|
||||
{
|
||||
{
|
||||
#ifdef EPOLL_SUPPORT
|
||||
enum MHD_StatusCode sc;
|
||||
enum MHD_StatusCode sc;
|
||||
|
||||
sc = MHD_daemon_epoll_ (daemon,
|
||||
MHD_NO);
|
||||
MHD_connection_cleanup_ (daemon);
|
||||
return sc;
|
||||
sc = MHD_daemon_epoll_ (daemon,
|
||||
MHD_NO);
|
||||
MHD_connection_cleanup_ (daemon);
|
||||
return sc;
|
||||
#else /* ! EPOLL_SUPPORT */
|
||||
return MHD_NO;
|
||||
return MHD_NO;
|
||||
#endif /* ! EPOLL_SUPPORT */
|
||||
}
|
||||
}
|
||||
|
||||
/* Resuming external connections when using an extern mainloop */
|
||||
if (! daemon->disallow_suspend_resume)
|
||||
(void) MHD_resume_suspended_connections_ (daemon);
|
||||
|
||||
return internal_run_from_select (daemon,
|
||||
read_fd_set,
|
||||
read_fd_set,
|
||||
write_fd_set,
|
||||
except_fd_set);
|
||||
except_fd_set);
|
||||
}
|
||||
|
||||
|
||||
@@ -646,7 +646,7 @@ MHD_daemon_run_from_select (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_select_ (struct MHD_Daemon *daemon,
|
||||
int may_block)
|
||||
int may_block)
|
||||
{
|
||||
int num_ready;
|
||||
fd_set rs;
|
||||
@@ -675,74 +675,75 @@ MHD_daemon_select_ (struct MHD_Daemon *daemon,
|
||||
may_block = MHD_NO;
|
||||
|
||||
if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
|
||||
{
|
||||
{
|
||||
|
||||
/* single-threaded, go over everything */
|
||||
if (MHD_SC_OK !=
|
||||
(sc = internal_get_fdset2 (daemon,
|
||||
&rs,
|
||||
&ws,
|
||||
&es,
|
||||
&maxsock,
|
||||
FD_SETSIZE)))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
sc,
|
||||
_("Could not obtain daemon fdsets"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
/* single-threaded, go over everything */
|
||||
if (MHD_SC_OK !=
|
||||
(sc = internal_get_fdset2 (daemon,
|
||||
&rs,
|
||||
&ws,
|
||||
&es,
|
||||
&maxsock,
|
||||
FD_SETSIZE)))
|
||||
{
|
||||
/* accept only, have one thread per connection */
|
||||
if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_socket)) &&
|
||||
(! daemon->was_quiesced) &&
|
||||
(! MHD_add_to_fd_set_ (ls,
|
||||
&rs,
|
||||
&maxsock,
|
||||
FD_SETSIZE)) )
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
|
||||
_("Could not add listen socket to fdset"));
|
||||
MHD_DLOG (daemon,
|
||||
sc,
|
||||
_ ("Could not obtain daemon fdsets"));
|
||||
#endif
|
||||
return MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
}
|
||||
}
|
||||
if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
|
||||
}
|
||||
else
|
||||
{
|
||||
/* accept only, have one thread per connection */
|
||||
if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_socket)) &&
|
||||
(! daemon->was_quiesced) &&
|
||||
(! MHD_add_to_fd_set_ (ls,
|
||||
&rs,
|
||||
&maxsock,
|
||||
FD_SETSIZE)) )
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
|
||||
_ ("Could not add listen socket to fdset"));
|
||||
#endif
|
||||
return MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
}
|
||||
}
|
||||
if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
|
||||
(! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
|
||||
&rs,
|
||||
&maxsock,
|
||||
FD_SETSIZE)) )
|
||||
{
|
||||
{
|
||||
#if defined(MHD_WINSOCK_SOCKETS)
|
||||
/* fdset limit reached, new connections
|
||||
cannot be handled. Remove listen socket FD
|
||||
from fdset and retry to add ITC FD. */
|
||||
if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_socket)) &&
|
||||
(! daemon->was_quiesced) )
|
||||
{
|
||||
FD_CLR (ls,
|
||||
&rs);
|
||||
if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_(daemon->itc),
|
||||
&rs,
|
||||
&maxsock,
|
||||
FD_SETSIZE))
|
||||
{
|
||||
/* fdset limit reached, new connections
|
||||
cannot be handled. Remove listen socket FD
|
||||
from fdset and retry to add ITC FD. */
|
||||
if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_socket)) &&
|
||||
(! daemon->was_quiesced) )
|
||||
{
|
||||
FD_CLR (ls,
|
||||
&rs);
|
||||
if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
|
||||
&rs,
|
||||
&maxsock,
|
||||
FD_SETSIZE))
|
||||
{
|
||||
#endif /* MHD_WINSOCK_SOCKETS */
|
||||
sc = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
sc = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
sc,
|
||||
_("Could not add control inter-thread communication channel FD to fdset"));
|
||||
MHD_DLOG (daemon,
|
||||
sc,
|
||||
_ (
|
||||
"Could not add control inter-thread communication channel FD to fdset"));
|
||||
#endif
|
||||
#if defined(MHD_WINSOCK_SOCKETS)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* MHD_WINSOCK_SOCKETS */
|
||||
}
|
||||
}
|
||||
/* Stop listening if we are at the configured connection limit */
|
||||
/* If we're at the connection limit, no point in really
|
||||
accepting new connections; however, make sure we do not miss
|
||||
@@ -750,35 +751,35 @@ MHD_daemon_select_ (struct MHD_Daemon *daemon,
|
||||
only do this optimization if we have a signaling ITC in
|
||||
place. */
|
||||
if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_socket)) &&
|
||||
(MHD_ITC_IS_VALID_(daemon->itc)) &&
|
||||
(MHD_ITC_IS_VALID_ (daemon->itc)) &&
|
||||
( (daemon->connections == daemon->global_connection_limit) ||
|
||||
(daemon->at_limit) ) )
|
||||
{
|
||||
FD_CLR (ls,
|
||||
&rs);
|
||||
}
|
||||
{
|
||||
FD_CLR (ls,
|
||||
&rs);
|
||||
}
|
||||
tv = NULL;
|
||||
if (MHD_SC_OK != sc)
|
||||
may_block = MHD_NO;
|
||||
if (MHD_NO == may_block)
|
||||
{
|
||||
timeout.tv_usec = 0;
|
||||
timeout.tv_sec = 0;
|
||||
tv = &timeout;
|
||||
}
|
||||
{
|
||||
timeout.tv_usec = 0;
|
||||
timeout.tv_sec = 0;
|
||||
tv = &timeout;
|
||||
}
|
||||
else if ( (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode) &&
|
||||
(MHD_SC_OK ==
|
||||
MHD_daemon_get_timeout (daemon,
|
||||
<imeout)) )
|
||||
{
|
||||
/* ltimeout is in ms */
|
||||
timeout.tv_usec = (ltimeout % 1000) * 1000;
|
||||
if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
|
||||
timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
|
||||
else
|
||||
timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE)(ltimeout / 1000);
|
||||
tv = &timeout;
|
||||
}
|
||||
(MHD_SC_OK ==
|
||||
MHD_daemon_get_timeout (daemon,
|
||||
<imeout)) )
|
||||
{
|
||||
/* ltimeout is in ms */
|
||||
timeout.tv_usec = (ltimeout % 1000) * 1000;
|
||||
if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
|
||||
timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
|
||||
else
|
||||
timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (ltimeout / 1000);
|
||||
tv = &timeout;
|
||||
}
|
||||
num_ready = MHD_SYS_select_ (maxsock + 1,
|
||||
&rs,
|
||||
&ws,
|
||||
@@ -787,24 +788,24 @@ MHD_daemon_select_ (struct MHD_Daemon *daemon,
|
||||
if (daemon->shutdown)
|
||||
return MHD_SC_DAEMON_ALREADY_SHUTDOWN;
|
||||
if (num_ready < 0)
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
{
|
||||
const int err = MHD_socket_get_error_ ();
|
||||
|
||||
if (MHD_SCKT_ERR_IS_EINTR_(err))
|
||||
return sc;
|
||||
if (MHD_SCKT_ERR_IS_EINTR_ (err))
|
||||
return sc;
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_UNEXPECTED_SELECT_ERROR,
|
||||
_("select failed: %s\n"),
|
||||
MHD_socket_strerr_ (err));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_UNEXPECTED_SELECT_ERROR,
|
||||
_ ("select failed: %s\n"),
|
||||
MHD_socket_strerr_ (err));
|
||||
#endif
|
||||
return MHD_SC_UNEXPECTED_SELECT_ERROR;
|
||||
}
|
||||
return MHD_SC_UNEXPECTED_SELECT_ERROR;
|
||||
}
|
||||
if (MHD_SC_OK !=
|
||||
(sc2 = internal_run_from_select (daemon,
|
||||
&rs,
|
||||
&ws,
|
||||
&es)))
|
||||
&rs,
|
||||
&ws,
|
||||
&es)))
|
||||
return sc2;
|
||||
return sc;
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
*/
|
||||
enum MHD_StatusCode
|
||||
MHD_daemon_select_ (struct MHD_Daemon *daemon,
|
||||
int may_block)
|
||||
MHD_NONNULL(1);
|
||||
int may_block)
|
||||
MHD_NONNULL (1);
|
||||
|
||||
|
||||
#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
|
||||
@@ -49,7 +49,7 @@ MHD_daemon_select_ (struct MHD_Daemon *daemon,
|
||||
*/
|
||||
void
|
||||
MHD_daemon_upgrade_connection_with_select_ (struct MHD_Connection *con)
|
||||
MHD_NONNULL(1);
|
||||
MHD_NONNULL (1);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+523
-514
@@ -46,63 +46,64 @@ configure_listen_reuse (struct MHD_Daemon *daemon)
|
||||
/* Apply the socket options according to
|
||||
listening_address_reuse. */
|
||||
if (daemon->allow_address_reuse)
|
||||
{
|
||||
/* User requested to allow reusing listening address:port. */
|
||||
#ifndef MHD_WINSOCK_SOCKETS
|
||||
/* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
|
||||
* it doesn't work. */
|
||||
if (0 > setsockopt (daemon->listen_socket,
|
||||
SOL_SOCKET,
|
||||
SO_REUSEADDR,
|
||||
(void *) &on,
|
||||
sizeof (on)))
|
||||
{
|
||||
/* User requested to allow reusing listening address:port. */
|
||||
#ifndef MHD_WINSOCK_SOCKETS
|
||||
/* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
|
||||
* it doesn't work. */
|
||||
if (0 > setsockopt (daemon->listen_socket,
|
||||
SOL_SOCKET,
|
||||
SO_REUSEADDR,
|
||||
(void *) &on,
|
||||
sizeof (on)))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED,
|
||||
_("setsockopt failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED;
|
||||
}
|
||||
return MHD_SC_OK;
|
||||
#endif /* ! MHD_WINSOCK_SOCKETS */
|
||||
/* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
|
||||
* Fail if SO_REUSEPORT is not defined or setsockopt fails.
|
||||
*/
|
||||
/* SO_REUSEADDR on W32 has the same semantics
|
||||
as SO_REUSEPORT on BSD/Linux */
|
||||
#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
|
||||
if (0 > setsockopt (daemon->listen_socket,
|
||||
SOL_SOCKET,
|
||||
#ifndef MHD_WINSOCK_SOCKETS
|
||||
SO_REUSEPORT,
|
||||
#else /* MHD_WINSOCK_SOCKETS */
|
||||
SO_REUSEADDR,
|
||||
#endif /* MHD_WINSOCK_SOCKETS */
|
||||
(void *) &on,
|
||||
sizeof (on)))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED,
|
||||
_("setsockopt failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED;
|
||||
}
|
||||
return MHD_SC_OK;
|
||||
#else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
|
||||
/* we're supposed to allow address:port re-use, but
|
||||
on this platform we cannot; fail hard */
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED,
|
||||
_("Cannot allow listening address reuse: SO_REUSEPORT not defined\n"));
|
||||
MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED,
|
||||
_ ("setsockopt failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED;
|
||||
#endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
|
||||
return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED;
|
||||
}
|
||||
return MHD_SC_OK;
|
||||
#endif /* ! MHD_WINSOCK_SOCKETS */
|
||||
/* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
|
||||
* Fail if SO_REUSEPORT is not defined or setsockopt fails.
|
||||
*/
|
||||
/* SO_REUSEADDR on W32 has the same semantics
|
||||
as SO_REUSEPORT on BSD/Linux */
|
||||
#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
|
||||
if (0 > setsockopt (daemon->listen_socket,
|
||||
SOL_SOCKET,
|
||||
#ifndef MHD_WINSOCK_SOCKETS
|
||||
SO_REUSEPORT,
|
||||
#else /* MHD_WINSOCK_SOCKETS */
|
||||
SO_REUSEADDR,
|
||||
#endif /* MHD_WINSOCK_SOCKETS */
|
||||
(void *) &on,
|
||||
sizeof (on)))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED,
|
||||
_ ("setsockopt failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED;
|
||||
}
|
||||
return MHD_SC_OK;
|
||||
#else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
|
||||
/* we're supposed to allow address:port re-use, but
|
||||
on this platform we cannot; fail hard */
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED,
|
||||
_ (
|
||||
"Cannot allow listening address reuse: SO_REUSEPORT not defined\n"));
|
||||
#endif
|
||||
return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED;
|
||||
#endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
|
||||
}
|
||||
|
||||
/* if (! daemon->allow_address_reuse) */
|
||||
/* User requested to disallow reusing listening address:port.
|
||||
@@ -111,32 +112,33 @@ configure_listen_reuse (struct MHD_Daemon *daemon)
|
||||
* Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
|
||||
* or setsockopt fails.
|
||||
*/
|
||||
#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
|
||||
#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
|
||||
(defined(__sun) && defined(SO_EXCLBIND))
|
||||
if (0 > setsockopt (daemon->listen_socket,
|
||||
SOL_SOCKET,
|
||||
SOL_SOCKET,
|
||||
#ifdef SO_EXCLUSIVEADDRUSE
|
||||
SO_EXCLUSIVEADDRUSE,
|
||||
SO_EXCLUSIVEADDRUSE,
|
||||
#else /* SO_EXCLBIND */
|
||||
SO_EXCLBIND,
|
||||
SO_EXCLBIND,
|
||||
#endif /* SO_EXCLBIND */
|
||||
(void *) &on,
|
||||
sizeof (on)))
|
||||
{
|
||||
(void *) &on,
|
||||
sizeof (on)))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_FAILED,
|
||||
_("setsockopt failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_FAILED,
|
||||
_ ("setsockopt failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_FAILED;
|
||||
}
|
||||
return MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_FAILED;
|
||||
}
|
||||
return MHD_SC_OK;
|
||||
#elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_NOT_SUPPORTED,
|
||||
_("Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n"));
|
||||
MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_NOT_SUPPORTED,
|
||||
_ (
|
||||
"Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n"));
|
||||
#endif
|
||||
return MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_NOT_SUPPORTED;
|
||||
#endif /* MHD_WINSOCK_SOCKETS */
|
||||
@@ -166,86 +168,86 @@ open_listen_socket (struct MHD_Daemon *daemon)
|
||||
pf = -1;
|
||||
/* Determine address family */
|
||||
switch (daemon->listen_af)
|
||||
{
|
||||
case MHD_AF_NONE:
|
||||
if (0 == daemon->listen_sa_len)
|
||||
{
|
||||
case MHD_AF_NONE:
|
||||
if (0 == daemon->listen_sa_len)
|
||||
{
|
||||
/* no listening desired, that's OK */
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
/* we have a listen address, get AF from there! */
|
||||
switch (daemon->listen_sa.ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
pf = PF_INET;
|
||||
use_v6 = false;
|
||||
break;
|
||||
/* no listening desired, that's OK */
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
/* we have a listen address, get AF from there! */
|
||||
switch (daemon->listen_sa.ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
pf = PF_INET;
|
||||
use_v6 = false;
|
||||
break;
|
||||
#ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
pf = PF_INET6;
|
||||
use_v6 = true;
|
||||
break;
|
||||
case AF_INET6:
|
||||
pf = PF_INET6;
|
||||
use_v6 = true;
|
||||
break;
|
||||
#endif
|
||||
#ifdef AF_UNIX
|
||||
case AF_UNIX:
|
||||
pf = PF_UNIX;
|
||||
use_v6 = false;
|
||||
break;
|
||||
case AF_UNIX:
|
||||
pf = PF_UNIX;
|
||||
use_v6 = false;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return MHD_SC_AF_NOT_SUPPORTED_BY_BUILD;
|
||||
} /* switch on ss_family */
|
||||
break; /* MHD_AF_NONE */
|
||||
case MHD_AF_AUTO:
|
||||
default:
|
||||
return MHD_SC_AF_NOT_SUPPORTED_BY_BUILD;
|
||||
} /* switch on ss_family */
|
||||
break; /* MHD_AF_NONE */
|
||||
case MHD_AF_AUTO:
|
||||
#if HAVE_INET6
|
||||
pf = PF_INET6;
|
||||
use_v6 = true;
|
||||
pf = PF_INET6;
|
||||
use_v6 = true;
|
||||
#else
|
||||
pf = PF_INET;
|
||||
use_v6 = false;
|
||||
pf = PF_INET;
|
||||
use_v6 = false;
|
||||
#endif
|
||||
break;
|
||||
case MHD_AF_INET4:
|
||||
use_v6 = false;
|
||||
pf = PF_INET;
|
||||
break;
|
||||
case MHD_AF_INET6:
|
||||
case MHD_AF_DUAL:
|
||||
break;
|
||||
case MHD_AF_INET4:
|
||||
use_v6 = false;
|
||||
pf = PF_INET;
|
||||
break;
|
||||
case MHD_AF_INET6:
|
||||
case MHD_AF_DUAL:
|
||||
#if HAVE_INET6
|
||||
pf = PF_INET6;
|
||||
use_v6 = true;
|
||||
break;
|
||||
pf = PF_INET6;
|
||||
use_v6 = true;
|
||||
break;
|
||||
#else
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD,
|
||||
_("IPv6 not supported by this build\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD,
|
||||
_ ("IPv6 not supported by this build\n"));
|
||||
#endif
|
||||
return MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD;
|
||||
return MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
mhd_assert (-1 != pf);
|
||||
/* try to open listen socket */
|
||||
try_open_listen_socket:
|
||||
daemon->listen_socket = MHD_socket_create_listen_(pf);
|
||||
try_open_listen_socket:
|
||||
daemon->listen_socket = MHD_socket_create_listen_ (pf);
|
||||
if ( (MHD_INVALID_SOCKET == daemon->listen_socket) &&
|
||||
(MHD_AF_AUTO == daemon->listen_af) &&
|
||||
(use_v6) )
|
||||
{
|
||||
use_v6 = false;
|
||||
pf = PF_INET;
|
||||
goto try_open_listen_socket;
|
||||
}
|
||||
{
|
||||
use_v6 = false;
|
||||
pf = PF_INET;
|
||||
goto try_open_listen_socket;
|
||||
}
|
||||
if (MHD_INVALID_SOCKET == daemon->listen_socket)
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET,
|
||||
_("Failed to create socket for listening: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET,
|
||||
_ ("Failed to create socket for listening: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET;
|
||||
}
|
||||
return MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET;
|
||||
}
|
||||
|
||||
if (MHD_SC_OK !=
|
||||
(sc = configure_listen_reuse (daemon)))
|
||||
@@ -253,156 +255,157 @@ open_listen_socket (struct MHD_Daemon *daemon)
|
||||
|
||||
/* configure for dual stack (or not) */
|
||||
if (use_v6)
|
||||
{
|
||||
{
|
||||
#if defined IPPROTO_IPV6 && defined IPV6_V6ONLY
|
||||
/* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
|
||||
(http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
|
||||
and may also be missing on older POSIX systems; good luck if you have any of those,
|
||||
your IPv6 socket may then also bind against IPv4 anyway... */
|
||||
const MHD_SCKT_OPT_BOOL_ v6_only =
|
||||
(MHD_AF_INET6 == daemon->listen_af);
|
||||
if (0 > setsockopt (daemon->listen_socket,
|
||||
IPPROTO_IPV6,
|
||||
IPV6_V6ONLY,
|
||||
(const void *) &v6_only,
|
||||
sizeof (v6_only)))
|
||||
{
|
||||
/* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
|
||||
(http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
|
||||
and may also be missing on older POSIX systems; good luck if you have any of those,
|
||||
your IPv6 socket may then also bind against IPv4 anyway... */
|
||||
const MHD_SCKT_OPT_BOOL_ v6_only =
|
||||
(MHD_AF_INET6 == daemon->listen_af);
|
||||
if (0 > setsockopt (daemon->listen_socket,
|
||||
IPPROTO_IPV6,
|
||||
IPV6_V6ONLY,
|
||||
(const void *) &v6_only,
|
||||
sizeof (v6_only)))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_FAILED,
|
||||
_("setsockopt failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_NOT_SUPPORTED,
|
||||
_("Cannot explicitly setup dual stack behavior on this platform\n"));
|
||||
#endif
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_FAILED,
|
||||
_ ("setsockopt failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_NOT_SUPPORTED,
|
||||
_ (
|
||||
"Cannot explicitly setup dual stack behavior on this platform\n"));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Determine address to bind to */
|
||||
if (0 != daemon->listen_sa_len)
|
||||
{
|
||||
/* Bind address explicitly given */
|
||||
sa = (const struct sockaddr *) &daemon->listen_sa;
|
||||
addrlen = daemon->listen_sa_len;
|
||||
}
|
||||
{
|
||||
/* Bind address explicitly given */
|
||||
sa = (const struct sockaddr *) &daemon->listen_sa;
|
||||
addrlen = daemon->listen_sa_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Compute bind address based on port and AF */
|
||||
{
|
||||
/* Compute bind address based on port and AF */
|
||||
#if HAVE_INET6
|
||||
if (use_v6)
|
||||
{
|
||||
if (use_v6)
|
||||
{
|
||||
#ifdef IN6ADDR_ANY_INIT
|
||||
static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
|
||||
static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
|
||||
#endif
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
|
||||
|
||||
addrlen = sizeof (struct sockaddr_in6);
|
||||
memset (sin6,
|
||||
0,
|
||||
sizeof (struct sockaddr_in6));
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_port = htons (daemon->listen_port);
|
||||
addrlen = sizeof (struct sockaddr_in6);
|
||||
memset (sin6,
|
||||
0,
|
||||
sizeof (struct sockaddr_in6));
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_port = htons (daemon->listen_port);
|
||||
#ifdef IN6ADDR_ANY_INIT
|
||||
sin6->sin6_addr = static_in6any;
|
||||
sin6->sin6_addr = static_in6any;
|
||||
#endif
|
||||
#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
|
||||
sin6->sin6_len = sizeof (struct sockaddr_in6);
|
||||
sin6->sin6_len = sizeof (struct sockaddr_in6);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
struct sockaddr_in *sin4 = (struct sockaddr_in *) &ss;
|
||||
|
||||
addrlen = sizeof (struct sockaddr_in);
|
||||
memset (sin4,
|
||||
0,
|
||||
sizeof (struct sockaddr_in));
|
||||
sin4->sin_family = AF_INET;
|
||||
sin4->sin_port = htons (daemon->listen_port);
|
||||
if (0 != INADDR_ANY)
|
||||
sin4->sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||
sin4->sin_len = sizeof (struct sockaddr_in);
|
||||
#endif
|
||||
}
|
||||
sa = (const struct sockaddr *) &ss;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
struct sockaddr_in *sin4 = (struct sockaddr_in *) &ss;
|
||||
|
||||
addrlen = sizeof (struct sockaddr_in);
|
||||
memset (sin4,
|
||||
0,
|
||||
sizeof (struct sockaddr_in));
|
||||
sin4->sin_family = AF_INET;
|
||||
sin4->sin_port = htons (daemon->listen_port);
|
||||
if (0 != INADDR_ANY)
|
||||
sin4->sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||
sin4->sin_len = sizeof (struct sockaddr_in);
|
||||
#endif
|
||||
}
|
||||
sa = (const struct sockaddr *) &ss;
|
||||
}
|
||||
|
||||
/* actually do the bind() */
|
||||
if (-1 == bind (daemon->listen_socket,
|
||||
sa,
|
||||
addrlen))
|
||||
{
|
||||
sa,
|
||||
addrlen))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
unsigned int port = 0;
|
||||
unsigned int port = 0;
|
||||
|
||||
switch (sa->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
if (addrlen == sizeof (struct sockaddr_in))
|
||||
port = ntohs (((const struct sockaddr_in *) sa)->sin_port);
|
||||
else
|
||||
port = UINT16_MAX + 1; /* indicate size error */
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (addrlen == sizeof (struct sockaddr_in6))
|
||||
port = ntohs (((const struct sockaddr_in6 *) sa)->sin6_port);
|
||||
else
|
||||
port = UINT16_MAX + 1; /* indicate size error */
|
||||
break;
|
||||
default:
|
||||
port = UINT_MAX; /* AF_UNIX? */
|
||||
break;
|
||||
}
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_SOCKET_BIND_FAILED,
|
||||
_("Failed to bind to port %u: %s\n"),
|
||||
port,
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_SC_LISTEN_SOCKET_BIND_FAILED;
|
||||
switch (sa->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
if (addrlen == sizeof (struct sockaddr_in))
|
||||
port = ntohs (((const struct sockaddr_in *) sa)->sin_port);
|
||||
else
|
||||
port = UINT16_MAX + 1; /* indicate size error */
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (addrlen == sizeof (struct sockaddr_in6))
|
||||
port = ntohs (((const struct sockaddr_in6 *) sa)->sin6_port);
|
||||
else
|
||||
port = UINT16_MAX + 1; /* indicate size error */
|
||||
break;
|
||||
default:
|
||||
port = UINT_MAX; /* AF_UNIX? */
|
||||
break;
|
||||
}
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_SOCKET_BIND_FAILED,
|
||||
_ ("Failed to bind to port %u: %s\n"),
|
||||
port,
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_SC_LISTEN_SOCKET_BIND_FAILED;
|
||||
}
|
||||
|
||||
/* setup TCP_FASTOPEN */
|
||||
#ifdef TCP_FASTOPEN
|
||||
if (MHD_FOM_DISABLE != daemon->fast_open_method)
|
||||
{
|
||||
if (0 != setsockopt (daemon->listen_socket,
|
||||
IPPROTO_TCP,
|
||||
TCP_FASTOPEN,
|
||||
&daemon->fo_queue_length,
|
||||
sizeof (daemon->fo_queue_length)))
|
||||
{
|
||||
if (0 != setsockopt (daemon->listen_socket,
|
||||
IPPROTO_TCP,
|
||||
TCP_FASTOPEN,
|
||||
&daemon->fo_queue_length,
|
||||
sizeof (daemon->fo_queue_length)))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_FAST_OPEN_FAILURE,
|
||||
_("setsockopt failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_FAST_OPEN_FAILURE,
|
||||
_ ("setsockopt failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
if (MHD_FOM_REQUIRE == daemon->fast_open_method)
|
||||
return MHD_SC_FAST_OPEN_FAILURE;
|
||||
}
|
||||
}
|
||||
if (MHD_FOM_REQUIRE == daemon->fast_open_method)
|
||||
return MHD_SC_FAST_OPEN_FAILURE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* setup listening */
|
||||
if (0 > listen (daemon->listen_socket,
|
||||
daemon->listen_backlog))
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_FAILURE,
|
||||
_("Failed to listen for connections: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_FAILURE,
|
||||
_ ("Failed to listen for connections: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_SC_LISTEN_FAILURE;
|
||||
}
|
||||
return MHD_SC_LISTEN_FAILURE;
|
||||
}
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
|
||||
@@ -426,65 +429,66 @@ get_listen_port_number (struct MHD_Daemon *daemon)
|
||||
return; /* nothing to be done */
|
||||
|
||||
memset (&servaddr,
|
||||
0,
|
||||
sizeof (struct sockaddr_storage));
|
||||
0,
|
||||
sizeof (struct sockaddr_storage));
|
||||
addrlen = sizeof (servaddr);
|
||||
if (0 != getsockname (daemon->listen_socket,
|
||||
(struct sockaddr *) &servaddr,
|
||||
&addrlen))
|
||||
{
|
||||
(struct sockaddr *) &servaddr,
|
||||
&addrlen))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_PORT_INTROSPECTION_FAILURE,
|
||||
_("Failed to get listen port number: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_PORT_INTROSPECTION_FAILURE,
|
||||
_ ("Failed to get listen port number: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif /* HAVE_MESSAGES */
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#ifdef MHD_POSIX_SOCKETS
|
||||
if (sizeof (servaddr) < addrlen)
|
||||
{
|
||||
/* should be impossible with `struct sockaddr_storage` */
|
||||
{
|
||||
/* should be impossible with `struct sockaddr_storage` */
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_PORT_INTROSPECTION_FAILURE,
|
||||
_("Failed to get listen port number (`struct sockaddr_storage` too small!?)\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_PORT_INTROSPECTION_FAILURE,
|
||||
_ (
|
||||
"Failed to get listen port number (`struct sockaddr_storage` too small!?)\n"));
|
||||
#endif /* HAVE_MESSAGES */
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif /* MHD_POSIX_SOCKETS */
|
||||
switch (servaddr.ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *s4 = (struct sockaddr_in *) &servaddr;
|
||||
struct sockaddr_in *s4 = (struct sockaddr_in *) &servaddr;
|
||||
|
||||
daemon->listen_port = ntohs (s4->sin_port);
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &servaddr;
|
||||
|
||||
daemon->listen_port = ntohs(s6->sin6_port);
|
||||
break;
|
||||
}
|
||||
#endif /* HAVE_INET6 */
|
||||
#ifdef AF_UNIX
|
||||
case AF_UNIX:
|
||||
daemon->listen_port = 0; /* special value for UNIX domain sockets */
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_PORT_INTROSPECTION_UNKNOWN_AF,
|
||||
_("Unknown address family!\n"));
|
||||
#endif
|
||||
daemon->listen_port = 0; /* ugh */
|
||||
daemon->listen_port = ntohs (s4->sin_port);
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &servaddr;
|
||||
|
||||
daemon->listen_port = ntohs (s6->sin6_port);
|
||||
break;
|
||||
}
|
||||
#endif /* HAVE_INET6 */
|
||||
#ifdef AF_UNIX
|
||||
case AF_UNIX:
|
||||
daemon->listen_port = 0; /* special value for UNIX domain sockets */
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_PORT_INTROSPECTION_UNKNOWN_AF,
|
||||
_ ("Unknown address family!\n"));
|
||||
#endif
|
||||
daemon->listen_port = 0; /* ugh */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -501,7 +505,7 @@ setup_epoll_fd (struct MHD_Daemon *daemon)
|
||||
int fd;
|
||||
|
||||
#ifndef HAVE_MESSAGES
|
||||
(void)daemon; /* Mute compiler warning. */
|
||||
(void) daemon; /* Mute compiler warning. */
|
||||
#endif /* ! HAVE_MESSAGES */
|
||||
|
||||
#ifdef USE_EPOLL_CREATE1
|
||||
@@ -510,24 +514,24 @@ setup_epoll_fd (struct MHD_Daemon *daemon)
|
||||
fd = epoll_create (MAX_EVENTS);
|
||||
#endif /* ! USE_EPOLL_CREATE1 */
|
||||
if (MHD_INVALID_SOCKET == fd)
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_CREATE_FAILED,
|
||||
_("Call to epoll_create1 failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_CREATE_FAILED,
|
||||
_ ("Call to epoll_create1 failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_INVALID_SOCKET;
|
||||
}
|
||||
#if !defined(USE_EPOLL_CREATE1)
|
||||
return MHD_INVALID_SOCKET;
|
||||
}
|
||||
#if ! defined(USE_EPOLL_CREATE1)
|
||||
if (! MHD_socket_noninheritable_ (fd))
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_CONFIGURE_NOINHERIT_FAILED,
|
||||
_("Failed to set noninheritable mode on epoll FD.\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_CONFIGURE_NOINHERIT_FAILED,
|
||||
_ ("Failed to set noninheritable mode on epoll FD.\n"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif /* ! USE_EPOLL_CREATE1 */
|
||||
return fd;
|
||||
}
|
||||
@@ -554,11 +558,11 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon)
|
||||
return MHD_SC_EPOLL_CTL_CREATE_FAILED;
|
||||
#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
|
||||
if (! daemon->disallow_upgrade)
|
||||
{
|
||||
daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
|
||||
if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
|
||||
return MHD_SC_EPOLL_CTL_CREATE_FAILED;
|
||||
}
|
||||
{
|
||||
daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
|
||||
if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
|
||||
return MHD_SC_EPOLL_CTL_CREATE_FAILED;
|
||||
}
|
||||
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
|
||||
if ( (MHD_INVALID_SOCKET == (ls = daemon->listen_socket)) ||
|
||||
(daemon->was_quiesced) )
|
||||
@@ -566,37 +570,37 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon)
|
||||
event.events = EPOLLIN;
|
||||
event.data.ptr = daemon;
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_ADD,
|
||||
ls,
|
||||
&event))
|
||||
EPOLL_CTL_ADD,
|
||||
ls,
|
||||
&event))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_ADD_FAILED,
|
||||
_ ("Call to epoll_ctl failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_SC_EPOLL_CTL_ADD_FAILED;
|
||||
}
|
||||
daemon->listen_socket_in_epoll = true;
|
||||
if (MHD_ITC_IS_VALID_ (daemon->itc))
|
||||
{
|
||||
event.events = EPOLLIN;
|
||||
event.data.ptr = (void *) daemon->epoll_itc_marker;
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_ADD,
|
||||
MHD_itc_r_fd_ (daemon->itc),
|
||||
&event))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_ADD_FAILED,
|
||||
_("Call to epoll_ctl failed: %s\n"),
|
||||
MHD_SC_EPOLL_CTL_ADD_FAILED,
|
||||
_ ("Call to epoll_ctl failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_SC_EPOLL_CTL_ADD_FAILED;
|
||||
}
|
||||
daemon->listen_socket_in_epoll = true;
|
||||
if (MHD_ITC_IS_VALID_(daemon->itc))
|
||||
{
|
||||
event.events = EPOLLIN;
|
||||
event.data.ptr = (void *) daemon->epoll_itc_marker;
|
||||
if (0 != epoll_ctl (daemon->epoll_fd,
|
||||
EPOLL_CTL_ADD,
|
||||
MHD_itc_r_fd_ (daemon->itc),
|
||||
&event))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_EPOLL_CTL_ADD_FAILED,
|
||||
_("Call to epoll_ctl failed: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
return MHD_SC_EPOLL_CTL_ADD_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
#endif
|
||||
@@ -616,35 +620,35 @@ MHD_polling_thread (void *cls)
|
||||
|
||||
MHD_thread_init_ (&daemon->pid);
|
||||
while (! daemon->shutdown)
|
||||
{
|
||||
switch (daemon->event_loop_syscall)
|
||||
{
|
||||
switch (daemon->event_loop_syscall)
|
||||
{
|
||||
case MHD_ELS_AUTO:
|
||||
MHD_PANIC ("MHD_ELS_AUTO should have been mapped to preferred style");
|
||||
break;
|
||||
case MHD_ELS_SELECT:
|
||||
MHD_daemon_select_ (daemon,
|
||||
MHD_YES);
|
||||
break;
|
||||
case MHD_ELS_POLL:
|
||||
case MHD_ELS_AUTO:
|
||||
MHD_PANIC ("MHD_ELS_AUTO should have been mapped to preferred style");
|
||||
break;
|
||||
case MHD_ELS_SELECT:
|
||||
MHD_daemon_select_ (daemon,
|
||||
MHD_YES);
|
||||
break;
|
||||
case MHD_ELS_POLL:
|
||||
#if HAVE_POLL
|
||||
MHD_daemon_poll_ (daemon,
|
||||
MHD_YES);
|
||||
MHD_daemon_poll_ (daemon,
|
||||
MHD_YES);
|
||||
#else
|
||||
MHD_PANIC ("MHD_ELS_POLL not supported, should have failed earlier");
|
||||
MHD_PANIC ("MHD_ELS_POLL not supported, should have failed earlier");
|
||||
#endif
|
||||
break;
|
||||
case MHD_ELS_EPOLL:
|
||||
break;
|
||||
case MHD_ELS_EPOLL:
|
||||
#ifdef EPOLL_SUPPORT
|
||||
MHD_daemon_epoll_ (daemon,
|
||||
MHD_YES);
|
||||
MHD_daemon_epoll_ (daemon,
|
||||
MHD_YES);
|
||||
#else
|
||||
MHD_PANIC ("MHD_ELS_EPOLL not supported, should have failed earlier");
|
||||
MHD_PANIC ("MHD_ELS_EPOLL not supported, should have failed earlier");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
MHD_connection_cleanup_ (daemon);
|
||||
break;
|
||||
}
|
||||
MHD_connection_cleanup_ (daemon);
|
||||
}
|
||||
/* Resume any pending for resume connections, join
|
||||
* all connection's threads (if any) and finally cleanup
|
||||
* everything. */
|
||||
@@ -652,7 +656,7 @@ MHD_polling_thread (void *cls)
|
||||
MHD_resume_suspended_connections_ (daemon);
|
||||
MHD_daemon_close_all_connections_ (daemon);
|
||||
|
||||
return (MHD_THRD_RTRN_TYPE_)0;
|
||||
return (MHD_THRD_RTRN_TYPE_) 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -669,114 +673,116 @@ setup_thread_pool (struct MHD_Daemon *daemon)
|
||||
* due to integer division). Also keep track of how many
|
||||
* connections are leftover after an equal split. */
|
||||
unsigned int conns_per_thread = daemon->global_connection_limit
|
||||
/ daemon->threading_mode;
|
||||
/ daemon->threading_mode;
|
||||
unsigned int leftover_conns = daemon->global_connection_limit
|
||||
% daemon->threading_mode;
|
||||
% daemon->threading_mode;
|
||||
int i;
|
||||
enum MHD_StatusCode sc;
|
||||
|
||||
/* Allocate memory for pooled objects */
|
||||
daemon->worker_pool = MHD_calloc_ (daemon->threading_mode,
|
||||
sizeof (struct MHD_Daemon));
|
||||
sizeof (struct MHD_Daemon));
|
||||
if (NULL == daemon->worker_pool)
|
||||
return MHD_SC_THREAD_POOL_MALLOC_FAILURE;
|
||||
|
||||
/* Start the workers in the pool */
|
||||
for (i = 0; i < daemon->threading_mode; i++)
|
||||
{
|
||||
/* Create copy of the Daemon object for each worker */
|
||||
struct MHD_Daemon *d = &daemon->worker_pool[i];
|
||||
|
||||
memcpy (d,
|
||||
daemon,
|
||||
sizeof (struct MHD_Daemon));
|
||||
/* Adjust pooling params for worker daemons; note that memcpy()
|
||||
has already copied MHD_USE_INTERNAL_POLLING_THREAD thread mode into
|
||||
the worker threads. */
|
||||
d->master = daemon;
|
||||
d->worker_pool_size = 0;
|
||||
d->worker_pool = NULL;
|
||||
/* Divide available connections evenly amongst the threads.
|
||||
* Thread indexes in [0, leftover_conns) each get one of the
|
||||
* leftover connections. */
|
||||
d->global_connection_limit = conns_per_thread;
|
||||
if (((unsigned int) i) < leftover_conns)
|
||||
++d->global_connection_limit;
|
||||
|
||||
if (! daemon->disable_itc)
|
||||
{
|
||||
/* Create copy of the Daemon object for each worker */
|
||||
struct MHD_Daemon *d = &daemon->worker_pool[i];
|
||||
|
||||
memcpy (d,
|
||||
daemon,
|
||||
sizeof (struct MHD_Daemon));
|
||||
/* Adjust pooling params for worker daemons; note that memcpy()
|
||||
has already copied MHD_USE_INTERNAL_POLLING_THREAD thread mode into
|
||||
the worker threads. */
|
||||
d->master = daemon;
|
||||
d->worker_pool_size = 0;
|
||||
d->worker_pool = NULL;
|
||||
/* Divide available connections evenly amongst the threads.
|
||||
* Thread indexes in [0, leftover_conns) each get one of the
|
||||
* leftover connections. */
|
||||
d->global_connection_limit = conns_per_thread;
|
||||
if (((unsigned int) i) < leftover_conns)
|
||||
++d->global_connection_limit;
|
||||
|
||||
if (! daemon->disable_itc)
|
||||
{
|
||||
if (! MHD_itc_init_ (d->itc))
|
||||
{
|
||||
if (! MHD_itc_init_ (d->itc))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ITC_INITIALIZATION_FAILED,
|
||||
_("Failed to create worker inter-thread communication channel: %s\n"),
|
||||
MHD_itc_last_strerror_() );
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ITC_INITIALIZATION_FAILED,
|
||||
_ (
|
||||
"Failed to create worker inter-thread communication channel: %s\n"),
|
||||
MHD_itc_last_strerror_ () );
|
||||
#endif
|
||||
sc = MHD_SC_ITC_INITIALIZATION_FAILED;
|
||||
goto thread_failed;
|
||||
}
|
||||
if ( (MHD_ELS_SELECT == daemon->event_loop_syscall) &&
|
||||
(! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (d->itc),
|
||||
NULL)) )
|
||||
{
|
||||
sc = MHD_SC_ITC_INITIALIZATION_FAILED;
|
||||
goto thread_failed;
|
||||
}
|
||||
if ( (MHD_ELS_SELECT == daemon->event_loop_syscall) &&
|
||||
(! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (d->itc),
|
||||
NULL)) )
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ITC_DESCRIPTOR_TOO_LARGE,
|
||||
_("File descriptor for inter-thread communication channel exceeds maximum value\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ITC_DESCRIPTOR_TOO_LARGE,
|
||||
_ (
|
||||
"File descriptor for inter-thread communication channel exceeds maximum value\n"));
|
||||
#endif
|
||||
MHD_itc_destroy_chk_ (d->itc);
|
||||
sc = MHD_SC_ITC_DESCRIPTOR_TOO_LARGE;
|
||||
goto thread_failed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MHD_itc_set_invalid_ (d->itc);
|
||||
}
|
||||
MHD_itc_destroy_chk_ (d->itc);
|
||||
sc = MHD_SC_ITC_DESCRIPTOR_TOO_LARGE;
|
||||
goto thread_failed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MHD_itc_set_invalid_ (d->itc);
|
||||
}
|
||||
|
||||
#ifdef EPOLL_SUPPORT
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
|
||||
(MHD_SC_OK != (sc = setup_epoll_to_listen (d))) )
|
||||
goto thread_failed;
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
|
||||
(MHD_SC_OK != (sc = setup_epoll_to_listen (d))) )
|
||||
goto thread_failed;
|
||||
#endif
|
||||
|
||||
/* Must init cleanup connection mutex for each worker */
|
||||
if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
|
||||
{
|
||||
/* Must init cleanup connection mutex for each worker */
|
||||
if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_THREAD_POOL_CREATE_MUTEX_FAILURE,
|
||||
_("MHD failed to initialize cleanup connection mutex\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_THREAD_POOL_CREATE_MUTEX_FAILURE,
|
||||
_ ("MHD failed to initialize cleanup connection mutex\n"));
|
||||
#endif
|
||||
if (! daemon->disable_itc)
|
||||
MHD_itc_destroy_chk_ (d->itc);
|
||||
sc = MHD_SC_THREAD_POOL_CREATE_MUTEX_FAILURE;
|
||||
goto thread_failed;
|
||||
}
|
||||
if (! daemon->disable_itc)
|
||||
MHD_itc_destroy_chk_ (d->itc);
|
||||
sc = MHD_SC_THREAD_POOL_CREATE_MUTEX_FAILURE;
|
||||
goto thread_failed;
|
||||
}
|
||||
|
||||
/* Spawn the worker thread */
|
||||
if (! MHD_create_named_thread_ (&d->pid,
|
||||
"MHD-worker",
|
||||
daemon->thread_stack_limit_b,
|
||||
&MHD_polling_thread,
|
||||
d))
|
||||
{
|
||||
/* Spawn the worker thread */
|
||||
if (! MHD_create_named_thread_ (&d->pid,
|
||||
"MHD-worker",
|
||||
daemon->thread_stack_limit_b,
|
||||
&MHD_polling_thread,
|
||||
d))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_THREAD_POOL_LAUNCH_FAILURE,
|
||||
_("Failed to create pool thread: %s\n"),
|
||||
MHD_strerror_ (errno));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_THREAD_POOL_LAUNCH_FAILURE,
|
||||
_ ("Failed to create pool thread: %s\n"),
|
||||
MHD_strerror_ (errno));
|
||||
#endif
|
||||
/* Free memory for this worker; cleanup below handles
|
||||
* all previously-created workers. */
|
||||
if (! daemon->disable_itc)
|
||||
MHD_itc_destroy_chk_ (d->itc);
|
||||
MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
|
||||
sc = MHD_SC_THREAD_POOL_LAUNCH_FAILURE;
|
||||
goto thread_failed;
|
||||
}
|
||||
} /* end for() */
|
||||
/* Free memory for this worker; cleanup below handles
|
||||
* all previously-created workers. */
|
||||
if (! daemon->disable_itc)
|
||||
MHD_itc_destroy_chk_ (d->itc);
|
||||
MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
|
||||
sc = MHD_SC_THREAD_POOL_LAUNCH_FAILURE;
|
||||
goto thread_failed;
|
||||
}
|
||||
} /* end for() */
|
||||
return MHD_SC_OK;
|
||||
|
||||
thread_failed:
|
||||
@@ -785,14 +791,14 @@ thread_failed:
|
||||
assumes a 0-sized thread pool means we had been in the default
|
||||
MHD_USE_INTERNAL_POLLING_THREAD mode. */
|
||||
if (0 == i)
|
||||
{
|
||||
if (NULL != daemon->worker_pool)
|
||||
{
|
||||
if (NULL != daemon->worker_pool)
|
||||
{
|
||||
free (daemon->worker_pool);
|
||||
daemon->worker_pool = NULL;
|
||||
}
|
||||
return MHD_SC_THREAD_LAUNCH_FAILURE;
|
||||
free (daemon->worker_pool);
|
||||
daemon->worker_pool = NULL;
|
||||
}
|
||||
return MHD_SC_THREAD_LAUNCH_FAILURE;
|
||||
}
|
||||
/* Shutdown worker threads we've already created. Pretend
|
||||
as though we had fully initialized our daemon, but
|
||||
with a smaller number of threads than had been
|
||||
@@ -817,63 +823,65 @@ MHD_daemon_start (struct MHD_Daemon *daemon)
|
||||
enum MHD_StatusCode sc;
|
||||
|
||||
if (MHD_ELS_AUTO == daemon->event_loop_syscall)
|
||||
{
|
||||
{
|
||||
#if EPOLL_SUPPORT
|
||||
/* We do not support thread-per-connection in combination
|
||||
with epoll, so use poll in this case, otherwise prefer
|
||||
epoll. */
|
||||
if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
|
||||
daemon->event_loop_syscall = MHD_ELS_POLL;
|
||||
else
|
||||
daemon->event_loop_syscall = MHD_ELS_EPOLL;
|
||||
#elif HAVE_POLL
|
||||
/* We do not support thread-per-connection in combination
|
||||
with epoll, so use poll in this case, otherwise prefer
|
||||
epoll. */
|
||||
if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
|
||||
daemon->event_loop_syscall = MHD_ELS_POLL;
|
||||
else
|
||||
daemon->event_loop_syscall = MHD_ELS_EPOLL;
|
||||
#elif HAVE_POLL
|
||||
daemon->event_loop_syscall = MHD_ELS_POLL;
|
||||
#else
|
||||
daemon->event_loop_syscall = MHD_ELS_SELECT;
|
||||
daemon->event_loop_syscall = MHD_ELS_SELECT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EPOLL_SUPPORT
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
|
||||
(0 == daemon->worker_pool_size) &&
|
||||
(MHD_INVALID_SOCKET != daemon->listen_socket) &&
|
||||
(MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) )
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_SYSCALL_THREAD_COMBINATION_INVALID,
|
||||
_("Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_SYSCALL_THREAD_COMBINATION_INVALID,
|
||||
_ (
|
||||
"Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
|
||||
#endif
|
||||
return MHD_SC_SYSCALL_THREAD_COMBINATION_INVALID;
|
||||
}
|
||||
return MHD_SC_SYSCALL_THREAD_COMBINATION_INVALID;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setup ITC */
|
||||
if ( (! daemon->disable_itc) &&
|
||||
(0 == daemon->worker_pool_size) )
|
||||
{
|
||||
if (! MHD_itc_init_ (daemon->itc))
|
||||
{
|
||||
if (! MHD_itc_init_ (daemon->itc))
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ITC_INITIALIZATION_FAILED,
|
||||
_("Failed to create inter-thread communication channel: %s\n"),
|
||||
MHD_itc_last_strerror_ ());
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ITC_INITIALIZATION_FAILED,
|
||||
_ ("Failed to create inter-thread communication channel: %s\n"),
|
||||
MHD_itc_last_strerror_ ());
|
||||
#endif
|
||||
return MHD_SC_ITC_INITIALIZATION_FAILED;
|
||||
}
|
||||
if ( (MHD_ELS_SELECT == daemon->event_loop_syscall) &&
|
||||
(! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (daemon->itc),
|
||||
NULL)) )
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ITC_DESCRIPTOR_TOO_LARGE,
|
||||
_("File descriptor for inter-thread communication channel exceeds maximum value\n"));
|
||||
#endif
|
||||
return MHD_SC_ITC_DESCRIPTOR_TOO_LARGE;
|
||||
}
|
||||
return MHD_SC_ITC_INITIALIZATION_FAILED;
|
||||
}
|
||||
if ( (MHD_ELS_SELECT == daemon->event_loop_syscall) &&
|
||||
(! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (daemon->itc),
|
||||
NULL)) )
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_ITC_DESCRIPTOR_TOO_LARGE,
|
||||
_ (
|
||||
"File descriptor for inter-thread communication channel exceeds maximum value\n"));
|
||||
#endif
|
||||
return MHD_SC_ITC_DESCRIPTOR_TOO_LARGE;
|
||||
}
|
||||
}
|
||||
|
||||
if (MHD_SC_OK != (sc = open_listen_socket (daemon)))
|
||||
return sc;
|
||||
@@ -881,39 +889,39 @@ MHD_daemon_start (struct MHD_Daemon *daemon)
|
||||
/* Check listen socket is in range (if we are limited) */
|
||||
if ( (MHD_INVALID_SOCKET != daemon->listen_socket) &&
|
||||
(MHD_ELS_SELECT == daemon->event_loop_syscall) &&
|
||||
(! MHD_SCKT_FD_FITS_FDSET_(daemon->listen_socket,
|
||||
NULL)) )
|
||||
{
|
||||
(! MHD_SCKT_FD_FITS_FDSET_ (daemon->listen_socket,
|
||||
NULL)) )
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_SOCKET_TOO_LARGE,
|
||||
_("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
|
||||
daemon->listen_socket,
|
||||
FD_SETSIZE);
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_SOCKET_TOO_LARGE,
|
||||
_ ("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
|
||||
daemon->listen_socket,
|
||||
FD_SETSIZE);
|
||||
#endif
|
||||
return MHD_SC_LISTEN_SOCKET_TOO_LARGE;
|
||||
}
|
||||
return MHD_SC_LISTEN_SOCKET_TOO_LARGE;
|
||||
}
|
||||
|
||||
/* set listen socket to non-blocking */
|
||||
if ( (MHD_INVALID_SOCKET != daemon->listen_socket) &&
|
||||
(! MHD_socket_nonblocking_ (daemon->listen_socket)) )
|
||||
{
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE,
|
||||
_("Failed to set nonblocking mode on listening socket: %s\n"),
|
||||
MHD_socket_last_strerr_());
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE,
|
||||
_ ("Failed to set nonblocking mode on listening socket: %s\n"),
|
||||
MHD_socket_last_strerr_ ());
|
||||
#endif
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) ||
|
||||
(daemon->worker_pool_size > 0) )
|
||||
{
|
||||
/* Accept must be non-blocking. Multiple children may wake
|
||||
* up to handle a new connection, but only one will win the
|
||||
* race. The others must immediately return. As this is
|
||||
* not possible, we must fail hard here. */
|
||||
return MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE;
|
||||
}
|
||||
if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) ||
|
||||
(daemon->worker_pool_size > 0) )
|
||||
{
|
||||
/* Accept must be non-blocking. Multiple children may wake
|
||||
* up to handle a new connection, but only one will win the
|
||||
* race. The others must immediately return. As this is
|
||||
* not possible, we must fail hard here. */
|
||||
return MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EPOLL_SUPPORT
|
||||
/* Setup epoll */
|
||||
@@ -928,30 +936,31 @@ MHD_daemon_start (struct MHD_Daemon *daemon)
|
||||
external event loop and do have a listen socket) */
|
||||
/* FIXME: why no worker thread if we have no listen socket? */
|
||||
if ( ( (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) ||
|
||||
(1 == daemon->threading_mode) ) &&
|
||||
(1 == daemon->threading_mode) ) &&
|
||||
(MHD_INVALID_SOCKET != daemon->listen_socket) &&
|
||||
(! MHD_create_named_thread_ (&daemon->pid,
|
||||
(MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
|
||||
? "MHD-listen"
|
||||
: "MHD-single",
|
||||
daemon->thread_stack_limit_b,
|
||||
&MHD_polling_thread,
|
||||
daemon) ) )
|
||||
{
|
||||
(MHD_TM_THREAD_PER_CONNECTION ==
|
||||
daemon->threading_mode)
|
||||
? "MHD-listen"
|
||||
: "MHD-single",
|
||||
daemon->thread_stack_limit_b,
|
||||
&MHD_polling_thread,
|
||||
daemon) ) )
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_THREAD_MAIN_LAUNCH_FAILURE,
|
||||
_("Failed to create listen thread: %s\n"),
|
||||
MHD_strerror_ (errno));
|
||||
MHD_DLOG (daemon,
|
||||
MHD_SC_THREAD_MAIN_LAUNCH_FAILURE,
|
||||
_ ("Failed to create listen thread: %s\n"),
|
||||
MHD_strerror_ (errno));
|
||||
#endif
|
||||
return MHD_SC_THREAD_MAIN_LAUNCH_FAILURE;
|
||||
}
|
||||
return MHD_SC_THREAD_MAIN_LAUNCH_FAILURE;
|
||||
}
|
||||
|
||||
/* Setup worker threads */
|
||||
/* FIXME: why no thread pool if we have no listen socket? */
|
||||
if ( (1 < daemon->threading_mode) &&
|
||||
(MHD_INVALID_SOCKET != daemon->listen_socket) &&
|
||||
(MHD_SC_OK != (sc = setup_thread_pool (daemon))) )
|
||||
(MHD_INVALID_SOCKET != daemon->listen_socket) &&
|
||||
(MHD_SC_OK != (sc = setup_thread_pool (daemon))) )
|
||||
return sc;
|
||||
|
||||
/* make sure we know our listen port (if any) */
|
||||
|
||||
+20
-20
@@ -36,7 +36,7 @@ volatile unsigned int global_init_count = 0;
|
||||
/**
|
||||
* Global initialisation mutex
|
||||
*/
|
||||
MHD_MUTEX_STATIC_DEFN_INIT_(global_init_mutex_);
|
||||
MHD_MUTEX_STATIC_DEFN_INIT_ (global_init_mutex_);
|
||||
#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
|
||||
|
||||
#endif
|
||||
@@ -59,21 +59,21 @@ static int mhd_winsock_inited_ = 0;
|
||||
*/
|
||||
static void
|
||||
mhd_panic_std (void *cls,
|
||||
const char *file,
|
||||
unsigned int line,
|
||||
const char *reason)
|
||||
const char *file,
|
||||
unsigned int line,
|
||||
const char *reason)
|
||||
{
|
||||
(void)cls; /* Mute compiler warning. */
|
||||
(void) cls; /* Mute compiler warning. */
|
||||
#ifdef HAVE_MESSAGES
|
||||
fprintf (stderr,
|
||||
_("Fatal error in GNU libmicrohttpd %s:%u: %s\n"),
|
||||
file,
|
||||
_ ("Fatal error in GNU libmicrohttpd %s:%u: %s\n"),
|
||||
file,
|
||||
line,
|
||||
reason);
|
||||
#else /* ! HAVE_MESSAGES */
|
||||
(void)file; /* Mute compiler warning. */
|
||||
(void)line; /* Mute compiler warning. */
|
||||
(void)reason; /* Mute compiler warning. */
|
||||
(void) file; /* Mute compiler warning. */
|
||||
(void) line; /* Mute compiler warning. */
|
||||
(void) reason; /* Mute compiler warning. */
|
||||
#endif
|
||||
abort ();
|
||||
}
|
||||
@@ -93,13 +93,13 @@ MHD_init (void)
|
||||
mhd_panic = &mhd_panic_std;
|
||||
|
||||
#if defined(_WIN32) && ! defined(__CYGWIN__)
|
||||
if (0 != WSAStartup (MAKEWORD(2, 2),
|
||||
&wsd))
|
||||
MHD_PANIC (_("Failed to initialize winsock\n"));
|
||||
if (0 != WSAStartup (MAKEWORD (2, 2),
|
||||
&wsd))
|
||||
MHD_PANIC (_ ("Failed to initialize winsock\n"));
|
||||
mhd_winsock_inited_ = 1;
|
||||
if ( (2 != LOBYTE(wsd.wVersion)) &&
|
||||
(2 != HIBYTE(wsd.wVersion)) )
|
||||
MHD_PANIC (_("Winsock version 2.2 is not available\n"));
|
||||
if ( (2 != LOBYTE (wsd.wVersion)) &&
|
||||
(2 != HIBYTE (wsd.wVersion)) )
|
||||
MHD_PANIC (_ ("Winsock version 2.2 is not available\n"));
|
||||
#endif
|
||||
MHD_monotonic_sec_counter_init ();
|
||||
#ifdef HAVE_FREEBSD_SENDFILE
|
||||
@@ -116,14 +116,14 @@ MHD_fini (void)
|
||||
{
|
||||
#if defined(_WIN32) && ! defined(__CYGWIN__)
|
||||
if (mhd_winsock_inited_)
|
||||
WSACleanup();
|
||||
WSACleanup ();
|
||||
#endif
|
||||
MHD_monotonic_sec_counter_finish ();
|
||||
}
|
||||
|
||||
#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
|
||||
|
||||
_SET_INIT_AND_DEINIT_FUNCS(MHD_init, MHD_fini);
|
||||
_SET_INIT_AND_DEINIT_FUNCS (MHD_init, MHD_fini);
|
||||
|
||||
#else
|
||||
|
||||
@@ -135,12 +135,12 @@ void
|
||||
MHD_check_global_init_ (void)
|
||||
{
|
||||
#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
|
||||
MHD_mutex_lock_chk_(&global_init_mutex_);
|
||||
MHD_mutex_lock_chk_ (&global_init_mutex_);
|
||||
#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
|
||||
if (0 == global_init_count++)
|
||||
MHD_init ();
|
||||
#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
|
||||
MHD_mutex_unlock_chk_(&global_init_mutex_);
|
||||
MHD_mutex_unlock_chk_ (&global_init_mutex_);
|
||||
#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
|
||||
}
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
* Do nothing - global initialisation is
|
||||
* performed by library constructor.
|
||||
*/
|
||||
#define MHD_check_global_init_() (void)0
|
||||
#define MHD_check_global_init_() (void) 0
|
||||
#else /* ! _AUTOINIT_FUNCS_ARE_SUPPORTED */
|
||||
/**
|
||||
* Check whether global initialisation was performed
|
||||
|
||||
+145
-145
@@ -35,50 +35,50 @@ const char *
|
||||
MHD_state_to_string (enum MHD_CONNECTION_STATE state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case MHD_CONNECTION_INIT:
|
||||
return "connection init";
|
||||
case MHD_CONNECTION_URL_RECEIVED:
|
||||
return "connection url received";
|
||||
case MHD_CONNECTION_HEADER_PART_RECEIVED:
|
||||
return "header partially received";
|
||||
case MHD_CONNECTION_HEADERS_RECEIVED:
|
||||
return "headers received";
|
||||
case MHD_CONNECTION_HEADERS_PROCESSED:
|
||||
return "headers processed";
|
||||
case MHD_CONNECTION_CONTINUE_SENDING:
|
||||
return "continue sending";
|
||||
case MHD_CONNECTION_CONTINUE_SENT:
|
||||
return "continue sent";
|
||||
case MHD_CONNECTION_BODY_RECEIVED:
|
||||
return "body received";
|
||||
case MHD_CONNECTION_FOOTER_PART_RECEIVED:
|
||||
return "footer partially received";
|
||||
case MHD_CONNECTION_FOOTERS_RECEIVED:
|
||||
return "footers received";
|
||||
case MHD_CONNECTION_HEADERS_SENDING:
|
||||
return "headers sending";
|
||||
case MHD_CONNECTION_HEADERS_SENT:
|
||||
return "headers sent";
|
||||
case MHD_CONNECTION_NORMAL_BODY_READY:
|
||||
return "normal body ready";
|
||||
case MHD_CONNECTION_NORMAL_BODY_UNREADY:
|
||||
return "normal body unready";
|
||||
case MHD_CONNECTION_CHUNKED_BODY_READY:
|
||||
return "chunked body ready";
|
||||
case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
|
||||
return "chunked body unready";
|
||||
case MHD_CONNECTION_BODY_SENT:
|
||||
return "body sent";
|
||||
case MHD_CONNECTION_FOOTERS_SENDING:
|
||||
return "footers sending";
|
||||
case MHD_CONNECTION_FOOTERS_SENT:
|
||||
return "footers sent";
|
||||
case MHD_CONNECTION_CLOSED:
|
||||
return "closed";
|
||||
default:
|
||||
return "unrecognized connection state";
|
||||
}
|
||||
{
|
||||
case MHD_CONNECTION_INIT:
|
||||
return "connection init";
|
||||
case MHD_CONNECTION_URL_RECEIVED:
|
||||
return "connection url received";
|
||||
case MHD_CONNECTION_HEADER_PART_RECEIVED:
|
||||
return "header partially received";
|
||||
case MHD_CONNECTION_HEADERS_RECEIVED:
|
||||
return "headers received";
|
||||
case MHD_CONNECTION_HEADERS_PROCESSED:
|
||||
return "headers processed";
|
||||
case MHD_CONNECTION_CONTINUE_SENDING:
|
||||
return "continue sending";
|
||||
case MHD_CONNECTION_CONTINUE_SENT:
|
||||
return "continue sent";
|
||||
case MHD_CONNECTION_BODY_RECEIVED:
|
||||
return "body received";
|
||||
case MHD_CONNECTION_FOOTER_PART_RECEIVED:
|
||||
return "footer partially received";
|
||||
case MHD_CONNECTION_FOOTERS_RECEIVED:
|
||||
return "footers received";
|
||||
case MHD_CONNECTION_HEADERS_SENDING:
|
||||
return "headers sending";
|
||||
case MHD_CONNECTION_HEADERS_SENT:
|
||||
return "headers sent";
|
||||
case MHD_CONNECTION_NORMAL_BODY_READY:
|
||||
return "normal body ready";
|
||||
case MHD_CONNECTION_NORMAL_BODY_UNREADY:
|
||||
return "normal body unready";
|
||||
case MHD_CONNECTION_CHUNKED_BODY_READY:
|
||||
return "chunked body ready";
|
||||
case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
|
||||
return "chunked body unready";
|
||||
case MHD_CONNECTION_BODY_SENT:
|
||||
return "body sent";
|
||||
case MHD_CONNECTION_FOOTERS_SENDING:
|
||||
return "footers sending";
|
||||
case MHD_CONNECTION_FOOTERS_SENT:
|
||||
return "footers sent";
|
||||
case MHD_CONNECTION_CLOSED:
|
||||
return "closed";
|
||||
default:
|
||||
return "unrecognized connection state";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -91,7 +91,7 @@ MHD_state_to_string (enum MHD_CONNECTION_STATE state)
|
||||
*/
|
||||
void
|
||||
MHD_DLOG (const struct MHD_Daemon *daemon,
|
||||
enum MHD_StatusCode sc,
|
||||
enum MHD_StatusCode sc,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
@@ -100,11 +100,11 @@ MHD_DLOG (const struct MHD_Daemon *daemon,
|
||||
if (NULL == daemon->logger)
|
||||
return;
|
||||
va_start (va,
|
||||
format);
|
||||
format);
|
||||
daemon->logger (daemon->logger_cls,
|
||||
sc,
|
||||
format,
|
||||
va);
|
||||
sc,
|
||||
format,
|
||||
va);
|
||||
va_end (va);
|
||||
}
|
||||
#endif
|
||||
@@ -120,7 +120,7 @@ MHD_unescape_plus (char *arg)
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p=strchr (arg, '+'); NULL != p; p = strchr (p + 1, '+'))
|
||||
for (p = strchr (arg, '+'); NULL != p; p = strchr (p + 1, '+'))
|
||||
*p = ' ';
|
||||
}
|
||||
|
||||
@@ -141,28 +141,28 @@ MHD_http_unescape (char *val)
|
||||
char *wpos = val;
|
||||
|
||||
while ('\0' != *rpos)
|
||||
{
|
||||
uint32_t num;
|
||||
switch (*rpos)
|
||||
{
|
||||
uint32_t num;
|
||||
switch (*rpos)
|
||||
{
|
||||
case '%':
|
||||
if (2 == MHD_strx_to_uint32_n_ (rpos + 1,
|
||||
2,
|
||||
&num))
|
||||
{
|
||||
*wpos = (char)((unsigned char) num);
|
||||
wpos++;
|
||||
rpos += 3;
|
||||
break;
|
||||
}
|
||||
/* TODO: add bad sequence handling */
|
||||
/* intentional fall through! */
|
||||
default:
|
||||
*wpos = *rpos;
|
||||
wpos++;
|
||||
rpos++;
|
||||
}
|
||||
case '%':
|
||||
if (2 == MHD_strx_to_uint32_n_ (rpos + 1,
|
||||
2,
|
||||
&num))
|
||||
{
|
||||
*wpos = (char) ((unsigned char) num);
|
||||
wpos++;
|
||||
rpos += 3;
|
||||
break;
|
||||
}
|
||||
/* TODO: add bad sequence handling */
|
||||
/* intentional fall through! */
|
||||
default:
|
||||
*wpos = *rpos;
|
||||
wpos++;
|
||||
rpos++;
|
||||
}
|
||||
}
|
||||
*wpos = '\0'; /* add 0-terminator */
|
||||
return wpos - val; /* = strlen(val) */
|
||||
}
|
||||
@@ -184,10 +184,10 @@ MHD_http_unescape (char *val)
|
||||
*/
|
||||
bool
|
||||
MHD_parse_arguments_ (struct MHD_Request *request,
|
||||
enum MHD_ValueKind kind,
|
||||
char *args,
|
||||
MHD_ArgumentIterator_ cb,
|
||||
unsigned int *num_headers)
|
||||
enum MHD_ValueKind kind,
|
||||
char *args,
|
||||
MHD_ArgumentIterator_ cb,
|
||||
unsigned int *num_headers)
|
||||
{
|
||||
struct MHD_Daemon *daemon = request->daemon;
|
||||
char *equals;
|
||||
@@ -195,88 +195,88 @@ MHD_parse_arguments_ (struct MHD_Request *request,
|
||||
|
||||
*num_headers = 0;
|
||||
while ( (NULL != args) &&
|
||||
('\0' != args[0]) )
|
||||
('\0' != args[0]) )
|
||||
{
|
||||
equals = strchr (args, '=');
|
||||
amper = strchr (args, '&');
|
||||
if (NULL == amper)
|
||||
{
|
||||
equals = strchr (args, '=');
|
||||
amper = strchr (args, '&');
|
||||
if (NULL == amper)
|
||||
{
|
||||
/* last argument */
|
||||
if (NULL == equals)
|
||||
{
|
||||
/* last argument, without '=' */
|
||||
MHD_unescape_plus (args);
|
||||
daemon->unescape_cb (daemon->unescape_cb_cls,
|
||||
request,
|
||||
args);
|
||||
if (! cb (request,
|
||||
args,
|
||||
NULL,
|
||||
kind))
|
||||
return false;
|
||||
(*num_headers)++;
|
||||
break;
|
||||
}
|
||||
/* got 'foo=bar' */
|
||||
equals[0] = '\0';
|
||||
equals++;
|
||||
MHD_unescape_plus (args);
|
||||
daemon->unescape_cb (daemon->unescape_cb_cls,
|
||||
request,
|
||||
args);
|
||||
MHD_unescape_plus (equals);
|
||||
daemon->unescape_cb (daemon->unescape_cb_cls,
|
||||
request,
|
||||
equals);
|
||||
if (! cb (request,
|
||||
args,
|
||||
equals,
|
||||
kind))
|
||||
return false;
|
||||
(*num_headers)++;
|
||||
break;
|
||||
}
|
||||
/* amper is non-NULL here */
|
||||
amper[0] = '\0';
|
||||
amper++;
|
||||
if ( (NULL == equals) ||
|
||||
(equals >= amper) )
|
||||
{
|
||||
/* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */
|
||||
MHD_unescape_plus (args);
|
||||
daemon->unescape_cb (daemon->unescape_cb_cls,
|
||||
request,
|
||||
args);
|
||||
if (! cb (request,
|
||||
args,
|
||||
NULL,
|
||||
kind))
|
||||
return false;
|
||||
/* continue with 'bar' */
|
||||
(*num_headers)++;
|
||||
args = amper;
|
||||
continue;
|
||||
}
|
||||
/* equals and amper are non-NULL here, and equals < amper,
|
||||
so we got regular 'foo=value&bar...'-kind of argument */
|
||||
/* last argument */
|
||||
if (NULL == equals)
|
||||
{
|
||||
/* last argument, without '=' */
|
||||
MHD_unescape_plus (args);
|
||||
daemon->unescape_cb (daemon->unescape_cb_cls,
|
||||
request,
|
||||
args);
|
||||
if (! cb (request,
|
||||
args,
|
||||
NULL,
|
||||
kind))
|
||||
return false;
|
||||
(*num_headers)++;
|
||||
break;
|
||||
}
|
||||
/* got 'foo=bar' */
|
||||
equals[0] = '\0';
|
||||
equals++;
|
||||
MHD_unescape_plus (args);
|
||||
daemon->unescape_cb (daemon->unescape_cb_cls,
|
||||
request,
|
||||
args);
|
||||
request,
|
||||
args);
|
||||
MHD_unescape_plus (equals);
|
||||
daemon->unescape_cb (daemon->unescape_cb_cls,
|
||||
request,
|
||||
equals);
|
||||
request,
|
||||
equals);
|
||||
if (! cb (request,
|
||||
args,
|
||||
equals,
|
||||
kind))
|
||||
args,
|
||||
equals,
|
||||
kind))
|
||||
return false;
|
||||
(*num_headers)++;
|
||||
args = amper;
|
||||
break;
|
||||
}
|
||||
/* amper is non-NULL here */
|
||||
amper[0] = '\0';
|
||||
amper++;
|
||||
if ( (NULL == equals) ||
|
||||
(equals >= amper) )
|
||||
{
|
||||
/* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */
|
||||
MHD_unescape_plus (args);
|
||||
daemon->unescape_cb (daemon->unescape_cb_cls,
|
||||
request,
|
||||
args);
|
||||
if (! cb (request,
|
||||
args,
|
||||
NULL,
|
||||
kind))
|
||||
return false;
|
||||
/* continue with 'bar' */
|
||||
(*num_headers)++;
|
||||
args = amper;
|
||||
continue;
|
||||
}
|
||||
/* equals and amper are non-NULL here, and equals < amper,
|
||||
so we got regular 'foo=value&bar...'-kind of argument */
|
||||
equals[0] = '\0';
|
||||
equals++;
|
||||
MHD_unescape_plus (args);
|
||||
daemon->unescape_cb (daemon->unescape_cb_cls,
|
||||
request,
|
||||
args);
|
||||
MHD_unescape_plus (equals);
|
||||
daemon->unescape_cb (daemon->unescape_cb_cls,
|
||||
request,
|
||||
equals);
|
||||
if (! cb (request,
|
||||
args,
|
||||
equals,
|
||||
kind))
|
||||
return false;
|
||||
(*num_headers)++;
|
||||
args = amper;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+82
-79
@@ -58,14 +58,16 @@
|
||||
*
|
||||
* @param msg error message (const char *)
|
||||
*/
|
||||
#define MHD_PANIC(msg) do { mhd_panic (mhd_panic_cls, __FILE__, __LINE__, msg); BUILTIN_NOT_REACHED; } while (0)
|
||||
#define MHD_PANIC(msg) do { mhd_panic (mhd_panic_cls, __FILE__, __LINE__, msg); \
|
||||
BUILTIN_NOT_REACHED; } while (0)
|
||||
#else
|
||||
/**
|
||||
* Trigger 'panic' action based on fatal errors.
|
||||
*
|
||||
* @param msg error message (const char *)
|
||||
*/
|
||||
#define MHD_PANIC(msg) do { mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); BUILTIN_NOT_REACHED; } while (0)
|
||||
#define MHD_PANIC(msg) do { mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); \
|
||||
BUILTIN_NOT_REACHED; } while (0)
|
||||
#endif
|
||||
|
||||
#include "mhd_threads.h"
|
||||
@@ -82,8 +84,8 @@
|
||||
*/
|
||||
void
|
||||
MHD_DLOG (const struct MHD_Daemon *daemon,
|
||||
enum MHD_StatusCode sc,
|
||||
const char *format,
|
||||
enum MHD_StatusCode sc,
|
||||
const char *format,
|
||||
...);
|
||||
#endif
|
||||
|
||||
@@ -93,9 +95,9 @@ MHD_DLOG (const struct MHD_Daemon *daemon,
|
||||
* @param fd the FD to close
|
||||
*/
|
||||
#define MHD_fd_close_chk_(fd) do { \
|
||||
if ( (0 != close ((fd)) && (EBADF == errno)) ) \
|
||||
MHD_PANIC(_("Failed to close FD.\n")); \
|
||||
} while(0)
|
||||
if ( (0 != close ((fd)) && (EBADF == errno)) ) \
|
||||
MHD_PANIC (_ ("Failed to close FD.\n")); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Should we perform additional sanity checks at runtime (on our internal
|
||||
@@ -128,10 +130,11 @@ extern MHD_PanicCallback mhd_panic;
|
||||
extern void *mhd_panic_cls;
|
||||
|
||||
/* If we have Clang or gcc >= 4.5, use __buildin_unreachable() */
|
||||
#if defined(__clang__) || (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
||||
#define BUILTIN_NOT_REACHED __builtin_unreachable()
|
||||
#if defined(__clang__) || (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= \
|
||||
5)
|
||||
#define BUILTIN_NOT_REACHED __builtin_unreachable ()
|
||||
#elif defined(_MSC_FULL_VER)
|
||||
#define BUILTIN_NOT_REACHED __assume(0)
|
||||
#define BUILTIN_NOT_REACHED __assume (0)
|
||||
#else
|
||||
#define BUILTIN_NOT_REACHED
|
||||
#endif
|
||||
@@ -140,7 +143,7 @@ extern void *mhd_panic_cls;
|
||||
/**
|
||||
* Determine length of static string / macro strings at compile time.
|
||||
*/
|
||||
#define MHD_STATICSTR_LEN_(macro) (sizeof(macro)/sizeof(char) - 1)
|
||||
#define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1)
|
||||
#endif /* ! MHD_STATICSTR_LEN_ */
|
||||
|
||||
|
||||
@@ -1534,8 +1537,8 @@ struct MHD_Daemon
|
||||
* @return #MHD_SC_OK on success, otherwise an error code
|
||||
*/
|
||||
typedef enum MHD_StatusCode
|
||||
(*ActionCallback) (void *cls,
|
||||
struct MHD_Request *request);
|
||||
(*ActionCallback)(void *cls,
|
||||
struct MHD_Request *request);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1703,9 +1706,9 @@ struct MHD_Response
|
||||
*/
|
||||
typedef bool
|
||||
(*MHD_ArgumentIterator_)(struct MHD_Request *request,
|
||||
const char *key,
|
||||
const char *value,
|
||||
enum MHD_ValueKind kind);
|
||||
const char *key,
|
||||
const char *value,
|
||||
enum MHD_ValueKind kind);
|
||||
|
||||
|
||||
/**
|
||||
@@ -1724,10 +1727,10 @@ typedef bool
|
||||
*/
|
||||
bool
|
||||
MHD_parse_arguments_ (struct MHD_Request *request,
|
||||
enum MHD_ValueKind kind,
|
||||
char *args,
|
||||
MHD_ArgumentIterator_ cb,
|
||||
unsigned int *num_headers);
|
||||
enum MHD_ValueKind kind,
|
||||
char *args,
|
||||
MHD_ArgumentIterator_ cb,
|
||||
unsigned int *num_headers);
|
||||
|
||||
|
||||
|
||||
@@ -1740,15 +1743,15 @@ MHD_parse_arguments_ (struct MHD_Request *request,
|
||||
* @param element element to insert
|
||||
*/
|
||||
#define DLL_insert(head,tail,element) do { \
|
||||
mhd_assert (NULL == (element)->next); \
|
||||
mhd_assert (NULL == (element)->prev); \
|
||||
(element)->next = (head); \
|
||||
(element)->prev = NULL; \
|
||||
if ((tail) == NULL) \
|
||||
(tail) = element; \
|
||||
else \
|
||||
(head)->prev = element; \
|
||||
(head) = (element); } while (0)
|
||||
mhd_assert (NULL == (element)->next); \
|
||||
mhd_assert (NULL == (element)->prev); \
|
||||
(element)->next = (head); \
|
||||
(element)->prev = NULL; \
|
||||
if ((tail) == NULL) \
|
||||
(tail) = element; \
|
||||
else \
|
||||
(head)->prev = element; \
|
||||
(head) = (element); } while (0)
|
||||
|
||||
|
||||
/**
|
||||
@@ -1760,18 +1763,18 @@ MHD_parse_arguments_ (struct MHD_Request *request,
|
||||
* @param element element to remove
|
||||
*/
|
||||
#define DLL_remove(head,tail,element) do { \
|
||||
mhd_assert ( (NULL != (element)->next) || ((element) == (tail))); \
|
||||
mhd_assert ( (NULL != (element)->prev) || ((element) == (head))); \
|
||||
if ((element)->prev == NULL) \
|
||||
(head) = (element)->next; \
|
||||
else \
|
||||
(element)->prev->next = (element)->next; \
|
||||
if ((element)->next == NULL) \
|
||||
(tail) = (element)->prev; \
|
||||
else \
|
||||
(element)->next->prev = (element)->prev; \
|
||||
(element)->next = NULL; \
|
||||
(element)->prev = NULL; } while (0)
|
||||
mhd_assert ( (NULL != (element)->next) || ((element) == (tail))); \
|
||||
mhd_assert ( (NULL != (element)->prev) || ((element) == (head))); \
|
||||
if ((element)->prev == NULL) \
|
||||
(head) = (element)->next; \
|
||||
else \
|
||||
(element)->prev->next = (element)->next; \
|
||||
if ((element)->next == NULL) \
|
||||
(tail) = (element)->prev; \
|
||||
else \
|
||||
(element)->next->prev = (element)->prev; \
|
||||
(element)->next = NULL; \
|
||||
(element)->prev = NULL; } while (0)
|
||||
|
||||
|
||||
|
||||
@@ -1784,15 +1787,15 @@ MHD_parse_arguments_ (struct MHD_Request *request,
|
||||
* @param element element to insert
|
||||
*/
|
||||
#define XDLL_insert(head,tail,element) do { \
|
||||
mhd_assert (NULL == (element)->nextX); \
|
||||
mhd_assert (NULL == (element)->prevX); \
|
||||
(element)->nextX = (head); \
|
||||
(element)->prevX = NULL; \
|
||||
if (NULL == (tail)) \
|
||||
(tail) = element; \
|
||||
else \
|
||||
(head)->prevX = element; \
|
||||
(head) = (element); } while (0)
|
||||
mhd_assert (NULL == (element)->nextX); \
|
||||
mhd_assert (NULL == (element)->prevX); \
|
||||
(element)->nextX = (head); \
|
||||
(element)->prevX = NULL; \
|
||||
if (NULL == (tail)) \
|
||||
(tail) = element; \
|
||||
else \
|
||||
(head)->prevX = element; \
|
||||
(head) = (element); } while (0)
|
||||
|
||||
|
||||
/**
|
||||
@@ -1804,18 +1807,18 @@ MHD_parse_arguments_ (struct MHD_Request *request,
|
||||
* @param element element to remove
|
||||
*/
|
||||
#define XDLL_remove(head,tail,element) do { \
|
||||
mhd_assert ( (NULL != (element)->nextX) || ((element) == (tail))); \
|
||||
mhd_assert ( (NULL != (element)->prevX) || ((element) == (head))); \
|
||||
if (NULL == (element)->prevX) \
|
||||
(head) = (element)->nextX; \
|
||||
else \
|
||||
(element)->prevX->nextX = (element)->nextX; \
|
||||
if (NULL == (element)->nextX) \
|
||||
(tail) = (element)->prevX; \
|
||||
else \
|
||||
(element)->nextX->prevX = (element)->prevX; \
|
||||
(element)->nextX = NULL; \
|
||||
(element)->prevX = NULL; } while (0)
|
||||
mhd_assert ( (NULL != (element)->nextX) || ((element) == (tail))); \
|
||||
mhd_assert ( (NULL != (element)->prevX) || ((element) == (head))); \
|
||||
if (NULL == (element)->prevX) \
|
||||
(head) = (element)->nextX; \
|
||||
else \
|
||||
(element)->prevX->nextX = (element)->nextX; \
|
||||
if (NULL == (element)->nextX) \
|
||||
(tail) = (element)->prevX; \
|
||||
else \
|
||||
(element)->nextX->prevX = (element)->prevX; \
|
||||
(element)->nextX = NULL; \
|
||||
(element)->prevX = NULL; } while (0)
|
||||
|
||||
|
||||
/**
|
||||
@@ -1827,13 +1830,13 @@ MHD_parse_arguments_ (struct MHD_Request *request,
|
||||
* @param element element to insert
|
||||
*/
|
||||
#define EDLL_insert(head,tail,element) do { \
|
||||
(element)->nextE = (head); \
|
||||
(element)->prevE = NULL; \
|
||||
if ((tail) == NULL) \
|
||||
(tail) = element; \
|
||||
else \
|
||||
(head)->prevE = element; \
|
||||
(head) = (element); } while (0)
|
||||
(element)->nextE = (head); \
|
||||
(element)->prevE = NULL; \
|
||||
if ((tail) == NULL) \
|
||||
(tail) = element; \
|
||||
else \
|
||||
(head)->prevE = element; \
|
||||
(head) = (element); } while (0)
|
||||
|
||||
|
||||
/**
|
||||
@@ -1845,16 +1848,16 @@ MHD_parse_arguments_ (struct MHD_Request *request,
|
||||
* @param element element to remove
|
||||
*/
|
||||
#define EDLL_remove(head,tail,element) do { \
|
||||
if ((element)->prevE == NULL) \
|
||||
(head) = (element)->nextE; \
|
||||
else \
|
||||
(element)->prevE->nextE = (element)->nextE; \
|
||||
if ((element)->nextE == NULL) \
|
||||
(tail) = (element)->prevE; \
|
||||
else \
|
||||
(element)->nextE->prevE = (element)->prevE; \
|
||||
(element)->nextE = NULL; \
|
||||
(element)->prevE = NULL; } while (0)
|
||||
if ((element)->prevE == NULL) \
|
||||
(head) = (element)->nextE; \
|
||||
else \
|
||||
(element)->prevE->nextE = (element)->nextE; \
|
||||
if ((element)->nextE == NULL) \
|
||||
(tail) = (element)->prevE; \
|
||||
else \
|
||||
(element)->nextE->prevE = (element)->prevE; \
|
||||
(element)->nextE = NULL; \
|
||||
(element)->prevE = NULL; } while (0)
|
||||
|
||||
|
||||
|
||||
|
||||
+109
-109
@@ -20,21 +20,21 @@
|
||||
#include "md5.h"
|
||||
#include "mhd_byteorder.h"
|
||||
|
||||
#define PUT_64BIT_LE(cp, value) do { \
|
||||
(cp)[7] = (uint8_t)((value) >> 56); \
|
||||
(cp)[6] = (uint8_t)((value) >> 48); \
|
||||
(cp)[5] = (uint8_t)((value) >> 40); \
|
||||
(cp)[4] = (uint8_t)((value) >> 32); \
|
||||
(cp)[3] = (uint8_t)((value) >> 24); \
|
||||
(cp)[2] = (uint8_t)((value) >> 16); \
|
||||
(cp)[1] = (uint8_t)((value) >> 8); \
|
||||
(cp)[0] = (uint8_t)((value)); } while (0)
|
||||
#define PUT_64BIT_LE(cp, value) do { \
|
||||
(cp)[7] = (uint8_t) ((value) >> 56); \
|
||||
(cp)[6] = (uint8_t) ((value) >> 48); \
|
||||
(cp)[5] = (uint8_t) ((value) >> 40); \
|
||||
(cp)[4] = (uint8_t) ((value) >> 32); \
|
||||
(cp)[3] = (uint8_t) ((value) >> 24); \
|
||||
(cp)[2] = (uint8_t) ((value) >> 16); \
|
||||
(cp)[1] = (uint8_t) ((value) >> 8); \
|
||||
(cp)[0] = (uint8_t) ((value)); } while (0)
|
||||
|
||||
#define PUT_32BIT_LE(cp, value) do { \
|
||||
(cp)[3] = (uint8_t)((value) >> 24); \
|
||||
(cp)[2] = (uint8_t)((value) >> 16); \
|
||||
(cp)[1] = (uint8_t)((value) >> 8); \
|
||||
(cp)[0] = (uint8_t)((value)); } while (0)
|
||||
#define PUT_32BIT_LE(cp, value) do { \
|
||||
(cp)[3] = (uint8_t) ((value) >> 24); \
|
||||
(cp)[2] = (uint8_t) ((value) >> 16); \
|
||||
(cp)[1] = (uint8_t) ((value) >> 8); \
|
||||
(cp)[0] = (uint8_t) ((value)); } while (0)
|
||||
|
||||
static uint8_t PADDING[MD5_BLOCK_SIZE] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -47,9 +47,9 @@ static uint8_t PADDING[MD5_BLOCK_SIZE] = {
|
||||
* initialization constants.
|
||||
*/
|
||||
void
|
||||
MHD_MD5Init(struct MD5Context *ctx)
|
||||
MHD_MD5Init (struct MD5Context *ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
if (! ctx)
|
||||
return;
|
||||
|
||||
ctx->count = 0;
|
||||
@@ -64,26 +64,26 @@ MHD_MD5Init(struct MD5Context *ctx)
|
||||
* of bytes.
|
||||
*/
|
||||
void
|
||||
MHD_MD5Update(struct MD5Context *ctx, const unsigned char *input, size_t len)
|
||||
MHD_MD5Update (struct MD5Context *ctx, const unsigned char *input, size_t len)
|
||||
{
|
||||
size_t have, need;
|
||||
|
||||
if (!ctx || !input)
|
||||
if (! ctx || ! input)
|
||||
return;
|
||||
|
||||
/* Check how many bytes we already have and how many more we need. */
|
||||
have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_SIZE - 1));
|
||||
have = (size_t) ((ctx->count >> 3) & (MD5_BLOCK_SIZE - 1));
|
||||
need = MD5_BLOCK_SIZE - have;
|
||||
|
||||
/* Update bitcount */
|
||||
ctx->count += (uint64_t)len << 3;
|
||||
ctx->count += (uint64_t) len << 3;
|
||||
|
||||
if (len >= need)
|
||||
{
|
||||
if (have != 0)
|
||||
{
|
||||
memcpy(ctx->buffer + have, input, need);
|
||||
MD5Transform(ctx->state, ctx->buffer);
|
||||
memcpy (ctx->buffer + have, input, need);
|
||||
MD5Transform (ctx->state, ctx->buffer);
|
||||
input += need;
|
||||
len -= need;
|
||||
have = 0;
|
||||
@@ -92,7 +92,7 @@ MHD_MD5Update(struct MD5Context *ctx, const unsigned char *input, size_t len)
|
||||
/* Process data in MD5_BLOCK_SIZE-byte chunks. */
|
||||
while (len >= MD5_BLOCK_SIZE)
|
||||
{
|
||||
MD5Transform(ctx->state, input);
|
||||
MD5Transform (ctx->state, input);
|
||||
input += MD5_BLOCK_SIZE;
|
||||
len -= MD5_BLOCK_SIZE;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ MHD_MD5Update(struct MD5Context *ctx, const unsigned char *input, size_t len)
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
if (len != 0)
|
||||
memcpy(ctx->buffer + have, input, len);
|
||||
memcpy (ctx->buffer + have, input, len);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -108,42 +108,42 @@ MHD_MD5Update(struct MD5Context *ctx, const unsigned char *input, size_t len)
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void
|
||||
MD5Pad(struct MD5Context *ctx)
|
||||
MD5Pad (struct MD5Context *ctx)
|
||||
{
|
||||
uint8_t count[8];
|
||||
size_t padlen;
|
||||
|
||||
if (!ctx)
|
||||
if (! ctx)
|
||||
return;
|
||||
|
||||
/* Convert count to 8 bytes in little endian order. */
|
||||
PUT_64BIT_LE(count, ctx->count);
|
||||
PUT_64BIT_LE (count, ctx->count);
|
||||
|
||||
/* Pad out to 56 mod 64. */
|
||||
padlen = MD5_BLOCK_SIZE -
|
||||
((ctx->count >> 3) & (MD5_BLOCK_SIZE - 1));
|
||||
padlen = MD5_BLOCK_SIZE
|
||||
- ((ctx->count >> 3) & (MD5_BLOCK_SIZE - 1));
|
||||
if (padlen < 1 + 8)
|
||||
padlen += MD5_BLOCK_SIZE;
|
||||
MHD_MD5Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */
|
||||
MHD_MD5Update(ctx, count, 8);
|
||||
MHD_MD5Update (ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */
|
||||
MHD_MD5Update (ctx, count, 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup--call MD5Pad, fill in digest and zero out ctx.
|
||||
*/
|
||||
void
|
||||
MHD_MD5Final(unsigned char digest[MD5_DIGEST_SIZE], struct MD5Context *ctx)
|
||||
MHD_MD5Final (unsigned char digest[MD5_DIGEST_SIZE], struct MD5Context *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!ctx || !digest)
|
||||
if (! ctx || ! digest)
|
||||
return;
|
||||
|
||||
MD5Pad(ctx);
|
||||
MD5Pad (ctx);
|
||||
for (i = 0; i < 4; i++)
|
||||
PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
|
||||
PUT_32BIT_LE (digest + i * 4, ctx->state[i]);
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
memset (ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
|
||||
@@ -151,13 +151,13 @@ MHD_MD5Final(unsigned char digest[MD5_DIGEST_SIZE], struct MD5Context *ctx)
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F2(x, y, z) F1 (z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
||||
(w += f (x, y, z) + data, w = w << s | w >> (32 - s), w += x)
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
@@ -165,20 +165,20 @@ MHD_MD5Final(unsigned char digest[MD5_DIGEST_SIZE], struct MD5Context *ctx)
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
void
|
||||
MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_SIZE])
|
||||
MD5Transform (uint32_t state[4], const uint8_t block[MD5_BLOCK_SIZE])
|
||||
{
|
||||
uint32_t a, b, c, d, in[MD5_BLOCK_SIZE / 4];
|
||||
|
||||
#if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
|
||||
memcpy(in, block, sizeof(in));
|
||||
memcpy (in, block, sizeof(in));
|
||||
#else
|
||||
for (a = 0; a < MD5_BLOCK_SIZE / 4; a++)
|
||||
{
|
||||
in[a] = (uint32_t)(
|
||||
(uint32_t)(block[a * 4 + 0]) |
|
||||
(uint32_t)(block[a * 4 + 1]) << 8 |
|
||||
(uint32_t)(block[a * 4 + 2]) << 16 |
|
||||
(uint32_t)(block[a * 4 + 3]) << 24);
|
||||
in[a] = (uint32_t) (
|
||||
(uint32_t) (block[a * 4 + 0])
|
||||
| (uint32_t) (block[a * 4 + 1]) << 8
|
||||
| (uint32_t) (block[a * 4 + 2]) << 16
|
||||
| (uint32_t) (block[a * 4 + 3]) << 24);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -187,73 +187,73 @@ MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_SIZE])
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
MD5STEP (F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP (F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP (F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP (F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP (F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP (F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP (F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP (F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP (F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP (F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP (F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP (F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP (F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP (F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP (F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP (F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
MD5STEP (F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP (F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP (F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP (F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP (F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP (F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP (F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP (F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP (F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP (F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP (F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP (F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP (F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP (F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP (F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP (F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
MD5STEP (F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP (F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP (F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP (F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP (F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP (F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP (F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP (F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP (F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP (F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP (F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP (F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP (F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP (F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP (F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP (F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
MD5STEP (F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP (F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP (F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP (F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP (F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP (F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP (F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP (F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP (F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP (F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP (F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP (F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP (F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP (F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP (F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP (F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
|
||||
+13
-11
@@ -20,45 +20,47 @@
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#define MD5_BLOCK_SIZE 64
|
||||
#define MD5_DIGEST_SIZE 16
|
||||
#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_SIZE * 2 + 1)
|
||||
#define MD5_BLOCK_SIZE 64
|
||||
#define MD5_DIGEST_SIZE 16
|
||||
#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_SIZE * 2 + 1)
|
||||
|
||||
struct MD5Context
|
||||
{
|
||||
uint32_t state[4]; /* state */
|
||||
uint64_t count; /* number of bits, mod 2^64 */
|
||||
uint8_t buffer[MD5_BLOCK_SIZE]; /* input buffer */
|
||||
uint32_t state[4]; /* state */
|
||||
uint64_t count; /* number of bits, mod 2^64 */
|
||||
uint8_t buffer[MD5_BLOCK_SIZE]; /* input buffer */
|
||||
};
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
void MHD_MD5Init(struct MD5Context *ctx);
|
||||
void MHD_MD5Init (struct MD5Context *ctx);
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
void MHD_MD5Update(struct MD5Context *ctx, const unsigned char *input, size_t len);
|
||||
void MHD_MD5Update (struct MD5Context *ctx, const unsigned char *input, size_t
|
||||
len);
|
||||
|
||||
/*
|
||||
* Pad pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void MD5Pad(struct MD5Context *ctx);
|
||||
void MD5Pad (struct MD5Context *ctx);
|
||||
|
||||
/*
|
||||
* Final wrapup--call MD5Pad, fill in digest and zero out ctx.
|
||||
*/
|
||||
void MHD_MD5Final(unsigned char digest[MD5_DIGEST_SIZE], struct MD5Context *ctx);
|
||||
void MHD_MD5Final (unsigned char digest[MD5_DIGEST_SIZE], struct
|
||||
MD5Context *ctx);
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MHD_MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
void MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_SIZE]);
|
||||
void MD5Transform (uint32_t state[4], const uint8_t block[MD5_BLOCK_SIZE]);
|
||||
|
||||
#endif /* !MHD_MD5_H */
|
||||
|
||||
+59
-59
@@ -25,11 +25,11 @@
|
||||
#include "memorypool.h"
|
||||
|
||||
/* define MAP_ANONYMOUS for Mac OS X */
|
||||
#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
|
||||
#if defined(MAP_ANON) && ! defined(MAP_ANONYMOUS)
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
#ifndef MAP_FAILED
|
||||
#define MAP_FAILED ((void*)-1)
|
||||
#define MAP_FAILED ((void*) -1)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -40,7 +40,7 @@
|
||||
/**
|
||||
* Round up 'n' to a multiple of ALIGN_SIZE.
|
||||
*/
|
||||
#define ROUND_TO_ALIGN(n) ((n+(ALIGN_SIZE-1)) & (~(ALIGN_SIZE-1)))
|
||||
#define ROUND_TO_ALIGN(n) ((n + (ALIGN_SIZE - 1)) & (~(ALIGN_SIZE - 1)))
|
||||
|
||||
|
||||
/**
|
||||
@@ -110,11 +110,11 @@ MHD_pool_create (size_t max)
|
||||
if (max <= 32 * 1024)
|
||||
pool->memory = MAP_FAILED;
|
||||
else
|
||||
#if defined(MAP_ANONYMOUS) && !defined(_WIN32)
|
||||
#if defined(MAP_ANONYMOUS) && ! defined(_WIN32)
|
||||
pool->memory = mmap (NULL,
|
||||
max,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS,
|
||||
-1,
|
||||
0);
|
||||
#elif defined(_WIN32)
|
||||
@@ -128,19 +128,19 @@ MHD_pool_create (size_t max)
|
||||
#endif
|
||||
if ( (MAP_FAILED == pool->memory) ||
|
||||
(NULL == pool->memory))
|
||||
{
|
||||
pool->memory = malloc (max);
|
||||
if (NULL == pool->memory)
|
||||
{
|
||||
pool->memory = malloc (max);
|
||||
if (NULL == pool->memory)
|
||||
{
|
||||
free (pool);
|
||||
return NULL;
|
||||
}
|
||||
pool->is_mmap = false;
|
||||
free (pool);
|
||||
return NULL;
|
||||
}
|
||||
pool->is_mmap = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pool->is_mmap = true;
|
||||
}
|
||||
{
|
||||
pool->is_mmap = true;
|
||||
}
|
||||
pool->pos = 0;
|
||||
pool->end = max;
|
||||
pool->size = max;
|
||||
@@ -161,7 +161,7 @@ MHD_pool_destroy (struct MemoryPool *pool)
|
||||
if (! pool->is_mmap)
|
||||
free (pool->memory);
|
||||
else
|
||||
#if defined(MAP_ANONYMOUS) && !defined(_WIN32)
|
||||
#if defined(MAP_ANONYMOUS) && ! defined(_WIN32)
|
||||
munmap (pool->memory,
|
||||
pool->size);
|
||||
#elif defined(_WIN32)
|
||||
@@ -201,7 +201,7 @@ MHD_pool_get_free (struct MemoryPool *pool)
|
||||
*/
|
||||
void *
|
||||
MHD_pool_allocate (struct MemoryPool *pool,
|
||||
size_t size,
|
||||
size_t size,
|
||||
int from_end)
|
||||
{
|
||||
void *ret;
|
||||
@@ -214,15 +214,15 @@ MHD_pool_allocate (struct MemoryPool *pool,
|
||||
(pool->pos + asize < pool->pos))
|
||||
return NULL;
|
||||
if (from_end == MHD_YES)
|
||||
{
|
||||
ret = &pool->memory[pool->end - asize];
|
||||
pool->end -= asize;
|
||||
}
|
||||
{
|
||||
ret = &pool->memory[pool->end - asize];
|
||||
pool->end -= asize;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = &pool->memory[pool->pos];
|
||||
pool->pos += asize;
|
||||
}
|
||||
{
|
||||
ret = &pool->memory[pool->pos];
|
||||
pool->pos += asize;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -247,8 +247,8 @@ MHD_pool_allocate (struct MemoryPool *pool,
|
||||
void *
|
||||
MHD_pool_reallocate (struct MemoryPool *pool,
|
||||
void *old,
|
||||
size_t old_size,
|
||||
size_t new_size)
|
||||
size_t old_size,
|
||||
size_t new_size)
|
||||
{
|
||||
void *ret;
|
||||
size_t asize;
|
||||
@@ -263,35 +263,35 @@ MHD_pool_reallocate (struct MemoryPool *pool,
|
||||
|
||||
if ( (pool->pos >= old_size) &&
|
||||
(&pool->memory[pool->pos - old_size] == old) )
|
||||
{
|
||||
/* was the previous allocation - optimize! */
|
||||
if (pool->pos + asize - old_size <= pool->end)
|
||||
{
|
||||
/* was the previous allocation - optimize! */
|
||||
if (pool->pos + asize - old_size <= pool->end)
|
||||
{
|
||||
/* fits */
|
||||
pool->pos += asize - old_size;
|
||||
if (asize < old_size) /* shrinking - zero again! */
|
||||
memset (&pool->memory[pool->pos],
|
||||
0,
|
||||
old_size - asize);
|
||||
return old;
|
||||
}
|
||||
/* does not fit */
|
||||
return NULL;
|
||||
/* fits */
|
||||
pool->pos += asize - old_size;
|
||||
if (asize < old_size) /* shrinking - zero again! */
|
||||
memset (&pool->memory[pool->pos],
|
||||
0,
|
||||
old_size - asize);
|
||||
return old;
|
||||
}
|
||||
/* does not fit */
|
||||
return NULL;
|
||||
}
|
||||
if (asize <= old_size)
|
||||
return old; /* cannot shrink, no need to move */
|
||||
if ((pool->pos + asize >= pool->pos) &&
|
||||
(pool->pos + asize <= pool->end))
|
||||
{
|
||||
/* fits */
|
||||
ret = &pool->memory[pool->pos];
|
||||
if (0 != old_size)
|
||||
memmove (ret,
|
||||
old,
|
||||
old_size);
|
||||
pool->pos += asize;
|
||||
return ret;
|
||||
}
|
||||
{
|
||||
/* fits */
|
||||
ret = &pool->memory[pool->pos];
|
||||
if (0 != old_size)
|
||||
memmove (ret,
|
||||
old,
|
||||
old_size);
|
||||
pool->pos += asize;
|
||||
return ret;
|
||||
}
|
||||
/* does not fit */
|
||||
return NULL;
|
||||
}
|
||||
@@ -312,19 +312,19 @@ MHD_pool_reallocate (struct MemoryPool *pool,
|
||||
*/
|
||||
void *
|
||||
MHD_pool_reset (struct MemoryPool *pool,
|
||||
void *keep,
|
||||
size_t copy_bytes,
|
||||
void *keep,
|
||||
size_t copy_bytes,
|
||||
size_t new_size)
|
||||
{
|
||||
if ( (NULL != keep) &&
|
||||
(keep != pool->memory) )
|
||||
{
|
||||
if (0 != copy_bytes)
|
||||
memmove (pool->memory,
|
||||
keep,
|
||||
copy_bytes);
|
||||
keep = pool->memory;
|
||||
}
|
||||
{
|
||||
if (0 != copy_bytes)
|
||||
memmove (pool->memory,
|
||||
keep,
|
||||
copy_bytes);
|
||||
keep = pool->memory;
|
||||
}
|
||||
pool->end = pool->size;
|
||||
/* technically not needed, but safer to zero out */
|
||||
if (pool->size > copy_bytes)
|
||||
|
||||
@@ -70,7 +70,7 @@ MHD_pool_destroy (struct MemoryPool *pool);
|
||||
*/
|
||||
void *
|
||||
MHD_pool_allocate (struct MemoryPool *pool,
|
||||
size_t size,
|
||||
size_t size,
|
||||
int from_end);
|
||||
|
||||
|
||||
@@ -93,9 +93,9 @@ MHD_pool_allocate (struct MemoryPool *pool,
|
||||
*/
|
||||
void *
|
||||
MHD_pool_reallocate (struct MemoryPool *pool,
|
||||
void *old,
|
||||
size_t old_size,
|
||||
size_t new_size);
|
||||
void *old,
|
||||
size_t old_size,
|
||||
size_t new_size);
|
||||
|
||||
|
||||
/**
|
||||
@@ -123,8 +123,8 @@ MHD_pool_get_free (struct MemoryPool *pool);
|
||||
*/
|
||||
void *
|
||||
MHD_pool_reset (struct MemoryPool *pool,
|
||||
void *keep,
|
||||
size_t copy_bytes,
|
||||
void *keep,
|
||||
size_t copy_bytes,
|
||||
size_t new_size);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,21 +28,21 @@
|
||||
|
||||
#include "mhd_options.h"
|
||||
#ifdef NDEBUG
|
||||
# define mhd_assert(ignore) ((void)0)
|
||||
# define mhd_assert(ignore) ((void) 0)
|
||||
#else /* _DEBUG */
|
||||
# ifdef HAVE_ASSERT
|
||||
# include <assert.h>
|
||||
# define mhd_assert(CHK) assert(CHK)
|
||||
# define mhd_assert(CHK) assert (CHK)
|
||||
# else /* ! HAVE_ASSERT */
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# define mhd_assert(CHK) \
|
||||
do { \
|
||||
if (!(CHK)) { \
|
||||
fprintf(stderr, "%s:%u Assertion failed: %s\nProgram aborted.\n", \
|
||||
__FILE__, (unsigned)__LINE__, #CHK); \
|
||||
fflush(stderr); abort(); } \
|
||||
} while(0)
|
||||
do { \
|
||||
if (! (CHK)) { \
|
||||
fprintf (stderr, "%s:%u Assertion failed: %s\nProgram aborted.\n", \
|
||||
__FILE__, (unsigned) __LINE__, #CHK); \
|
||||
fflush (stderr); abort (); } \
|
||||
} while (0)
|
||||
# endif /* ! HAVE_ASSERT */
|
||||
#endif /* _DEBUG */
|
||||
|
||||
|
||||
+27
-20
@@ -71,7 +71,8 @@
|
||||
#if defined(__BYTE_ORDER__)
|
||||
#if defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define _MHD_BYTE_ORDER _MHD_BIG_ENDIAN
|
||||
#elif defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#elif defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == \
|
||||
__ORDER_LITTLE_ENDIAN__
|
||||
#define _MHD_BYTE_ORDER _MHD_LITTLE_ENDIAN
|
||||
#elif defined(__ORDER_PDP_ENDIAN__) && __BYTE_ORDER__ == __ORDER_PDP_ENDIAN__
|
||||
#define _MHD_BYTE_ORDER _MHD_PDP_ENDIAN
|
||||
@@ -106,36 +107,40 @@
|
||||
/* Byte order specification didn't detected in system headers */
|
||||
/* Try some guessing */
|
||||
|
||||
#if (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) || \
|
||||
(defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN))
|
||||
#if (defined(__BIG_ENDIAN__) && ! defined(__LITTLE_ENDIAN__)) || \
|
||||
(defined(_BIG_ENDIAN) && ! defined(_LITTLE_ENDIAN))
|
||||
/* Seems that we are on big endian platform */
|
||||
#define _MHD_BYTE_ORDER _MHD_BIG_ENDIAN
|
||||
#elif (defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \
|
||||
(defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN))
|
||||
#elif (defined(__LITTLE_ENDIAN__) && ! defined(__BIG_ENDIAN__)) || \
|
||||
(defined(_LITTLE_ENDIAN) && ! defined(_BIG_ENDIAN))
|
||||
/* Seems that we are on little endian platform */
|
||||
#define _MHD_BYTE_ORDER _MHD_LITTLE_ENDIAN
|
||||
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || \
|
||||
defined(_M_X64) || defined(_M_AMD64) || defined(i386) || defined(__i386) || \
|
||||
defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || \
|
||||
defined(_M_IX86) || defined(_X86_) || defined (__THW_INTEL__)
|
||||
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || \
|
||||
defined(__x86_64) || \
|
||||
defined(_M_X64) || defined(_M_AMD64) || defined(i386) || defined(__i386) || \
|
||||
defined(__i386__) || defined(__i486__) || defined(__i586__) || \
|
||||
defined(__i686__) || \
|
||||
defined(_M_IX86) || defined(_X86_) || defined (__THW_INTEL__)
|
||||
/* x86 family is little endian */
|
||||
#define _MHD_BYTE_ORDER _MHD_LITTLE_ENDIAN
|
||||
#elif defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
|
||||
defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__)
|
||||
defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__)
|
||||
/* Looks like we are on ARM/MIPS in big endian mode */
|
||||
#define _MHD_BYTE_ORDER _MHD_BIG_ENDIAN
|
||||
#elif defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \
|
||||
defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__)
|
||||
defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__)
|
||||
/* Looks like we are on ARM/MIPS in little endian mode */
|
||||
#define _MHD_BYTE_ORDER _MHD_LITTLE_ENDIAN
|
||||
#elif defined(__m68k__) || defined(M68000) || defined(__hppa__) || defined(__hppa) || \
|
||||
defined(__HPPA__) || defined(__370__) || defined(__THW_370__) || \
|
||||
defined(__s390__) || defined(__s390x__) || defined(__SYSC_ZARCH__)
|
||||
#elif defined(__m68k__) || defined(M68000) || defined(__hppa__) || \
|
||||
defined(__hppa) || \
|
||||
defined(__HPPA__) || defined(__370__) || defined(__THW_370__) || \
|
||||
defined(__s390__) || defined(__s390x__) || defined(__SYSC_ZARCH__)
|
||||
/* Looks like we are on big endian platform */
|
||||
#define _MHD_BYTE_ORDER _MHD_BIG_ENDIAN
|
||||
#elif defined(__ia64__) || defined(_IA64) || defined(__IA64__) || defined(__ia64) || \
|
||||
defined(_M_IA64) || defined(__itanium__) || defined(__bfin__) || \
|
||||
defined(__BFIN__) || defined(bfin) || defined(BFIN)
|
||||
#elif defined(__ia64__) || defined(_IA64) || defined(__IA64__) || \
|
||||
defined(__ia64) || \
|
||||
defined(_M_IA64) || defined(__itanium__) || defined(__bfin__) || \
|
||||
defined(__BFIN__) || defined(bfin) || defined(BFIN)
|
||||
/* Looks like we are on little endian platform */
|
||||
#define _MHD_BYTE_ORDER _MHD_LITTLE_ENDIAN
|
||||
#elif defined(_WIN32)
|
||||
@@ -151,9 +156,11 @@
|
||||
#ifdef _MHD_BYTE_ORDER
|
||||
/* Some safety checks */
|
||||
#if defined(WORDS_BIGENDIAN) && _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN
|
||||
#error Configure detected big endian byte order but headers specify different byte order
|
||||
#elif !defined(WORDS_BIGENDIAN) && _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
|
||||
#error Configure did not detect big endian byte order but headers specify big endian byte order
|
||||
#error \
|
||||
Configure detected big endian byte order but headers specify different byte order
|
||||
#elif ! defined(WORDS_BIGENDIAN) && _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
|
||||
#error \
|
||||
Configure did not detect big endian byte order but headers specify big endian byte order
|
||||
#endif /* !WORDS_BIGENDIAN && _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN */
|
||||
#endif /* _MHD_BYTE_ORDER */
|
||||
|
||||
|
||||
+12
-12
@@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "mhd_compat.h"
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#if defined(_WIN32) && ! defined(__CYGWIN__)
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#ifndef HAVE_SNPRINTF
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <string.h> /* for memset() */
|
||||
#endif /* ! HAVE_CALLOC */
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#if defined(_WIN32) && ! defined(__CYGWIN__)
|
||||
|
||||
#ifndef HAVE_SNPRINTF
|
||||
/* Emulate snprintf function on W32 */
|
||||
@@ -61,16 +61,16 @@ W32_snprintf (char *__restrict s,
|
||||
format,
|
||||
args);
|
||||
va_end (args);
|
||||
if ((int)n == ret)
|
||||
if ((int) n == ret)
|
||||
s[n - 1] = 0;
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
}
|
||||
va_start(args,
|
||||
format);
|
||||
va_start (args,
|
||||
format);
|
||||
ret = _vscprintf (format,
|
||||
args);
|
||||
va_end(args);
|
||||
va_end (args);
|
||||
if ( (0 <= ret) &&
|
||||
(0 != n) &&
|
||||
(NULL == s) )
|
||||
@@ -85,30 +85,30 @@ W32_snprintf (char *__restrict s,
|
||||
#ifndef HAVE_CALLOC
|
||||
|
||||
#ifdef __has_builtin
|
||||
# if __has_builtin(__builtin_mul_overflow)
|
||||
# if __has_builtin (__builtin_mul_overflow)
|
||||
# define MHD_HAVE_NUL_OVERFLOW 1
|
||||
# endif
|
||||
#elif __GNUC__+0 >= 5
|
||||
#elif __GNUC__ + 0 >= 5
|
||||
# define MHD_HAVE_NUL_OVERFLOW 1
|
||||
#endif /* __GNUC__ >= 5 */
|
||||
|
||||
|
||||
void *MHD_calloc_(size_t nelem, size_t elsize)
|
||||
void *MHD_calloc_ (size_t nelem, size_t elsize)
|
||||
{
|
||||
size_t alloc_size;
|
||||
void *ptr;
|
||||
#ifdef MHD_HAVE_NUL_OVERFLOW
|
||||
if (__builtin_mul_overflow(nelem, elsize, &alloc_size) || 0 == alloc_size)
|
||||
if (__builtin_mul_overflow (nelem, elsize, &alloc_size) ||(0 == alloc_size))
|
||||
return NULL;
|
||||
#else /* ! MHD_HAVE_NUL_OVERFLOW */
|
||||
alloc_size = nelem * elsize;
|
||||
if (0 == alloc_size || elsize != alloc_size / nelem)
|
||||
if ((0 == alloc_size)||(elsize != alloc_size / nelem))
|
||||
return NULL;
|
||||
#endif /* ! MHD_HAVE_NUL_OVERFLOW */
|
||||
ptr = malloc (alloc_size);
|
||||
if (NULL == ptr)
|
||||
return NULL;
|
||||
memset(ptr, 0, alloc_size);
|
||||
memset (ptr, 0, alloc_size);
|
||||
return ptr;
|
||||
}
|
||||
#endif /* ! HAVE_CALLOC */
|
||||
|
||||
+10
-8
@@ -40,8 +40,8 @@
|
||||
#include <string.h>
|
||||
#endif /* HAVE_STRING_H */
|
||||
|
||||
/* MHD_strerror_ is strerror */
|
||||
#define MHD_strerror_(errnum) strerror((errnum))
|
||||
/* MHD_strerror_ is strerror */
|
||||
#define MHD_strerror_(errnum) strerror ((errnum))
|
||||
|
||||
/* Platform-independent snprintf name */
|
||||
#if defined(HAVE_SNPRINTF)
|
||||
@@ -49,10 +49,12 @@
|
||||
#else /* ! HAVE_SNPRINTF */
|
||||
#if defined(_WIN32) && ! defined(__CYGWIN__)
|
||||
/* Emulate snprintf function on W32 */
|
||||
int W32_snprintf(char *__restrict s, size_t n, const char *__restrict format, ...);
|
||||
int W32_snprintf (char *__restrict s, size_t n, const char *__restrict format,
|
||||
...);
|
||||
#define MHD_snprintf_ W32_snprintf
|
||||
#else /* ! _WIN32 || __CYGWIN__ */
|
||||
#error Your platform does not support snprintf() and MHD does not know how to emulate it on your platform.
|
||||
#error \
|
||||
Your platform does not support snprintf() and MHD does not know how to emulate it on your platform.
|
||||
#endif /* ! _WIN32 || __CYGWIN__ */
|
||||
#endif /* ! HAVE_SNPRINTF */
|
||||
|
||||
@@ -61,14 +63,14 @@ int W32_snprintf(char *__restrict s, size_t n, const char *__restrict format, ..
|
||||
* Generate pseudo random number at least 30-bit wide.
|
||||
* @return pseudo random number at least 30-bit wide.
|
||||
*/
|
||||
#define MHD_random_() random()
|
||||
#define MHD_random_() random ()
|
||||
#else /* HAVE_RANDOM */
|
||||
#ifdef HAVE_RAND
|
||||
/**
|
||||
* Generate pseudo random number at least 30-bit wide.
|
||||
* @return pseudo random number at least 30-bit wide.
|
||||
*/
|
||||
#define MHD_random_() ( (((long)rand()) << 15) + (long)rand() )
|
||||
#define MHD_random_() ( (((long) rand ()) << 15) + (long) rand () )
|
||||
#endif /* HAVE_RAND */
|
||||
#endif /* HAVE_RANDOM */
|
||||
|
||||
@@ -76,12 +78,12 @@ int W32_snprintf(char *__restrict s, size_t n, const char *__restrict format, ..
|
||||
/**
|
||||
* MHD_calloc_ is platform-independent calloc()
|
||||
*/
|
||||
#define MHD_calloc_(n,s) calloc((n),(s))
|
||||
#define MHD_calloc_(n,s) calloc ((n),(s))
|
||||
#else /* ! HAVE_CALLOC */
|
||||
/**
|
||||
* MHD_calloc_ is platform-independent calloc()
|
||||
*/
|
||||
void *MHD_calloc_(size_t nelem, size_t elsize);
|
||||
void *MHD_calloc_ (size_t nelem, size_t elsize);
|
||||
#endif /* ! HAVE_CALLOC */
|
||||
|
||||
#endif /* MHD_COMPAT_H */
|
||||
|
||||
+3
-3
@@ -34,7 +34,7 @@
|
||||
|
||||
|
||||
#if defined(_MHD_ITC_PIPE)
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
#if ! defined(_WIN32) || defined(__CYGWIN__)
|
||||
|
||||
#ifndef HAVE_PIPE2_FUNC
|
||||
/**
|
||||
@@ -48,7 +48,7 @@ MHD_itc_nonblocking_ (struct MHD_itc_ itc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i=0;i<2;i++)
|
||||
for (i = 0; i<2; i++)
|
||||
{
|
||||
int flags;
|
||||
|
||||
@@ -63,7 +63,7 @@ MHD_itc_nonblocking_ (struct MHD_itc_ itc)
|
||||
flags | O_NONBLOCK)) )
|
||||
return 0;
|
||||
}
|
||||
return !0;
|
||||
return ! 0;
|
||||
}
|
||||
#endif /* ! HAVE_PIPE2_FUNC */
|
||||
#endif /* !_WIN32 || __CYGWIN__ */
|
||||
|
||||
+54
-49
@@ -41,8 +41,9 @@
|
||||
# include <stdlib.h>
|
||||
/* Simple implementation of MHD_PANIC, to be used outside lib */
|
||||
# define MHD_PANIC(msg) do { fprintf (stderr, \
|
||||
"Abnormal termination at %d line in file %s: %s\n", \
|
||||
(int)__LINE__, __FILE__, msg); abort();} while(0)
|
||||
"Abnormal termination at %d line in file %s: %s\n", \
|
||||
(int) __LINE__, __FILE__, msg); abort (); \
|
||||
} while (0)
|
||||
#endif /* ! MHD_PANIC */
|
||||
|
||||
#if defined(_MHD_ITC_EVENTFD)
|
||||
@@ -63,12 +64,13 @@
|
||||
* @param itc the itc to initialise
|
||||
* @return non-zero if succeeded, zero otherwise
|
||||
*/
|
||||
#define MHD_itc_init_(itc) (-1 != ((itc).fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK)))
|
||||
#define MHD_itc_init_(itc) (-1 != ((itc).fd = eventfd (0, EFD_CLOEXEC \
|
||||
| EFD_NONBLOCK)))
|
||||
|
||||
/**
|
||||
* Get description string of last errno for itc operations.
|
||||
*/
|
||||
#define MHD_itc_last_strerror_() strerror(errno)
|
||||
#define MHD_itc_last_strerror_() strerror (errno)
|
||||
|
||||
/**
|
||||
* Internal static const helper for MHD_itc_activate_()
|
||||
@@ -82,7 +84,8 @@ static const uint64_t _MHD_itc_wr_data = 1;
|
||||
* @return non-zero if succeeded, zero otherwise
|
||||
*/
|
||||
#define MHD_itc_activate_(itc, str) \
|
||||
((write((itc).fd, (const void*)&_MHD_itc_wr_data, 8) > 0) || (EAGAIN == errno))
|
||||
((write ((itc).fd, (const void*) &_MHD_itc_wr_data, 8) > 0) || (EAGAIN == \
|
||||
errno))
|
||||
|
||||
/**
|
||||
* Return read FD of @a itc which can be used for poll(), select() etc.
|
||||
@@ -104,8 +107,8 @@ static const uint64_t _MHD_itc_wr_data = 1;
|
||||
*/
|
||||
#define MHD_itc_clear_(itc) \
|
||||
do { uint64_t __b; int __r; \
|
||||
__r = read((itc).fd, &__b, sizeof(__b)); \
|
||||
(void)__r; } while(0)
|
||||
__r = read ((itc).fd, &__b, sizeof(__b)); \
|
||||
(void) __r; } while (0)
|
||||
|
||||
/**
|
||||
* Destroy previously initialised ITC. Note that close()
|
||||
@@ -155,20 +158,20 @@ static const uint64_t _MHD_itc_wr_data = 1;
|
||||
* @return non-zero if succeeded, zero otherwise
|
||||
*/
|
||||
#ifdef HAVE_PIPE2_FUNC
|
||||
# define MHD_itc_init_(itc) (!pipe2((itc).fd, O_CLOEXEC | O_NONBLOCK))
|
||||
# define MHD_itc_init_(itc) (! pipe2 ((itc).fd, O_CLOEXEC | O_NONBLOCK))
|
||||
#else /* ! HAVE_PIPE2_FUNC */
|
||||
# define MHD_itc_init_(itc) \
|
||||
( (!pipe((itc).fd)) ? \
|
||||
(MHD_itc_nonblocking_((itc)) ? \
|
||||
(!0) : \
|
||||
(MHD_itc_destroy_((itc)), 0) ) \
|
||||
: (0) )
|
||||
( (! pipe ((itc).fd)) ? \
|
||||
(MHD_itc_nonblocking_ ((itc)) ? \
|
||||
(! 0) : \
|
||||
(MHD_itc_destroy_ ((itc)), 0) ) \
|
||||
: (0) )
|
||||
#endif /* ! HAVE_PIPE2_FUNC */
|
||||
|
||||
/**
|
||||
* Get description string of last errno for itc operations.
|
||||
*/
|
||||
#define MHD_itc_last_strerror_() strerror(errno)
|
||||
#define MHD_itc_last_strerror_() strerror (errno)
|
||||
|
||||
/**
|
||||
* Activate signal on @a itc
|
||||
@@ -177,7 +180,7 @@ static const uint64_t _MHD_itc_wr_data = 1;
|
||||
* @return non-zero if succeeded, zero otherwise
|
||||
*/
|
||||
#define MHD_itc_activate_(itc, str) \
|
||||
((write((itc).fd[1], (const void*)(str), 1) > 0) || (EAGAIN == errno))
|
||||
((write ((itc).fd[1], (const void*) (str), 1) > 0) || (EAGAIN == errno))
|
||||
|
||||
|
||||
/**
|
||||
@@ -200,8 +203,8 @@ static const uint64_t _MHD_itc_wr_data = 1;
|
||||
*/
|
||||
#define MHD_itc_clear_(itc) do \
|
||||
{ long __b; \
|
||||
while(0 < read((itc).fd[0], &__b, sizeof(__b))) \
|
||||
{} } while(0)
|
||||
while (0 < read ((itc).fd[0], &__b, sizeof(__b))) \
|
||||
{} } while (0)
|
||||
|
||||
/**
|
||||
* Destroy previously initialised ITC
|
||||
@@ -210,8 +213,8 @@ static const uint64_t _MHD_itc_wr_data = 1;
|
||||
*/
|
||||
#define MHD_itc_destroy_(itc) \
|
||||
( (0 == close ((itc).fd[0])) ? \
|
||||
(0 == close ((itc).fd[1])) : \
|
||||
((close ((itc).fd[1])), 0) )
|
||||
(0 == close ((itc).fd[1])) : \
|
||||
((close ((itc).fd[1])), 0) )
|
||||
|
||||
/**
|
||||
* Check whether ITC has valid value.
|
||||
@@ -231,14 +234,14 @@ static const uint64_t _MHD_itc_wr_data = 1;
|
||||
#define MHD_itc_set_invalid_(itc) ((itc).fd[0] = (itc).fd[1] = -1)
|
||||
|
||||
#ifndef HAVE_PIPE2_FUNC
|
||||
/**
|
||||
* Change itc FD options to be non-blocking.
|
||||
*
|
||||
* @param fd the FD to manipulate
|
||||
* @return non-zero if succeeded, zero otherwise
|
||||
*/
|
||||
int
|
||||
MHD_itc_nonblocking_ (struct MHD_itc_ itc);
|
||||
/**
|
||||
* Change itc FD options to be non-blocking.
|
||||
*
|
||||
* @param fd the FD to manipulate
|
||||
* @return non-zero if succeeded, zero otherwise
|
||||
*/
|
||||
int
|
||||
MHD_itc_nonblocking_ (struct MHD_itc_ itc);
|
||||
#endif /* ! HAVE_PIPE2_FUNC */
|
||||
|
||||
|
||||
@@ -255,20 +258,20 @@ static const uint64_t _MHD_itc_wr_data = 1;
|
||||
* @return non-zero if succeeded, zero otherwise
|
||||
*/
|
||||
#ifdef MHD_socket_pair_nblk_
|
||||
# define MHD_itc_init_(itc) MHD_socket_pair_nblk_((itc).sk)
|
||||
# define MHD_itc_init_(itc) MHD_socket_pair_nblk_ ((itc).sk)
|
||||
#else /* ! MHD_socket_pair_nblk_ */
|
||||
# define MHD_itc_init_(itc) \
|
||||
(MHD_socket_pair_((itc).sk) ? \
|
||||
(MHD_itc_nonblocking_((itc)) ? \
|
||||
(!0) : \
|
||||
(MHD_itc_destroy_((itc)), 0) ) \
|
||||
: (0))
|
||||
(MHD_socket_pair_ ((itc).sk) ? \
|
||||
(MHD_itc_nonblocking_ ((itc)) ? \
|
||||
(! 0) : \
|
||||
(MHD_itc_destroy_ ((itc)), 0) ) \
|
||||
: (0))
|
||||
#endif /* ! MHD_socket_pair_nblk_ */
|
||||
|
||||
/**
|
||||
* Get description string of last error for itc operations.
|
||||
*/
|
||||
#define MHD_itc_last_strerror_() MHD_socket_last_strerr_()
|
||||
#define MHD_itc_last_strerror_() MHD_socket_last_strerr_ ()
|
||||
|
||||
/**
|
||||
* Activate signal on @a itc
|
||||
@@ -277,8 +280,8 @@ static const uint64_t _MHD_itc_wr_data = 1;
|
||||
* @return non-zero if succeeded, zero otherwise
|
||||
*/
|
||||
#define MHD_itc_activate_(itc, str) \
|
||||
((MHD_send_((itc).sk[1], (str), 1) > 0) || \
|
||||
(MHD_SCKT_ERR_IS_EAGAIN_(MHD_socket_get_error_())))
|
||||
((MHD_send_ ((itc).sk[1], (str), 1) > 0) || \
|
||||
(MHD_SCKT_ERR_IS_EAGAIN_ (MHD_socket_get_error_ ())))
|
||||
|
||||
/**
|
||||
* Return read FD of @a itc which can be used for poll(), select() etc.
|
||||
@@ -300,10 +303,10 @@ static const uint64_t _MHD_itc_wr_data = 1;
|
||||
*/
|
||||
#define MHD_itc_clear_(itc) do \
|
||||
{ long __b; \
|
||||
while(0 < recv((itc).sk[0], \
|
||||
(char*)&__b, \
|
||||
sizeof(__b), 0)) \
|
||||
{} } while(0)
|
||||
while (0 < recv ((itc).sk[0], \
|
||||
(char*) &__b, \
|
||||
sizeof(__b), 0)) \
|
||||
{} } while (0)
|
||||
|
||||
/**
|
||||
* Destroy previously initialised ITC
|
||||
@@ -311,9 +314,9 @@ static const uint64_t _MHD_itc_wr_data = 1;
|
||||
* @return non-zero if succeeded, zero otherwise
|
||||
*/
|
||||
#define MHD_itc_destroy_(itc) \
|
||||
( MHD_socket_close_((itc).sk[0]) ? \
|
||||
MHD_socket_close_((itc).sk[1]) : \
|
||||
((void)MHD_socket_close_((itc).sk[1]), 0) )
|
||||
(MHD_socket_close_ ((itc).sk[0]) ? \
|
||||
MHD_socket_close_ ((itc).sk[1]) : \
|
||||
((void) MHD_socket_close_ ((itc).sk[1]), 0) )
|
||||
|
||||
|
||||
/**
|
||||
@@ -331,10 +334,12 @@ static const uint64_t _MHD_itc_wr_data = 1;
|
||||
* Set @a itc to invalid value.
|
||||
* @param itc the itc to set
|
||||
*/
|
||||
#define MHD_itc_set_invalid_(itc) ((itc).sk[0] = (itc).sk[1] = MHD_INVALID_SOCKET)
|
||||
#define MHD_itc_set_invalid_(itc) ((itc).sk[0] = (itc).sk[1] = \
|
||||
MHD_INVALID_SOCKET)
|
||||
|
||||
#ifndef MHD_socket_pair_nblk_
|
||||
# define MHD_itc_nonblocking_(pip) (MHD_socket_nonblocking_((pip).sk[0]) && MHD_socket_nonblocking_((pip).sk[1]))
|
||||
# define MHD_itc_nonblocking_(pip) (MHD_socket_nonblocking_ ((pip).sk[0]) && \
|
||||
MHD_socket_nonblocking_ ((pip).sk[1]))
|
||||
#endif /* ! MHD_socket_pair_nblk_ */
|
||||
|
||||
#endif /* _MHD_ITC_SOCKETPAIR */
|
||||
@@ -345,9 +350,9 @@ static const uint64_t _MHD_itc_wr_data = 1;
|
||||
* @param itc the itc to destroy
|
||||
*/
|
||||
#define MHD_itc_destroy_chk_(itc) do { \
|
||||
if (!MHD_itc_destroy_(itc)) \
|
||||
MHD_PANIC(_("Failed to destroy ITC.\n")); \
|
||||
} while(0)
|
||||
if (! MHD_itc_destroy_ (itc)) \
|
||||
MHD_PANIC (_ ("Failed to destroy ITC.\n")); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Check whether ITC has invalid value.
|
||||
@@ -358,6 +363,6 @@ static const uint64_t _MHD_itc_wr_data = 1;
|
||||
* @return boolean true if @a itc has invalid value,
|
||||
* boolean false otherwise.
|
||||
*/
|
||||
#define MHD_ITC_IS_INVALID_(itc) (! MHD_ITC_IS_VALID_(itc))
|
||||
#define MHD_ITC_IS_INVALID_(itc) (! MHD_ITC_IS_VALID_ (itc))
|
||||
|
||||
#endif /* MHD_ITC_H */
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "mhd_options.h"
|
||||
|
||||
/* Force socketpair on native W32 */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(_MHD_ITC_SOCKETPAIR)
|
||||
#if defined(_WIN32) && ! defined(__CYGWIN__) && ! defined(_MHD_ITC_SOCKETPAIR)
|
||||
#error _MHD_ITC_SOCKETPAIR is not defined on naitive W32 platform
|
||||
#endif /* _WIN32 && !__CYGWIN__ && !_MHD_ITC_SOCKETPAIR */
|
||||
|
||||
|
||||
+19
-19
@@ -32,17 +32,17 @@
|
||||
#include <limits.h>
|
||||
#endif /* HAVE_LIMITS_H */
|
||||
|
||||
#define MHD_UNSIGNED_TYPE_MAX_(type) ((type)-1)
|
||||
#define MHD_UNSIGNED_TYPE_MAX_(type) ((type) - 1)
|
||||
/* Assume 8 bits per byte, no padding bits. */
|
||||
#define MHD_SIGNED_TYPE_MAX_(type) \
|
||||
( (type)((( ((type)1) << (sizeof(type)*8 - 2)) - 1)*2 + 1) )
|
||||
#define MHD_TYPE_IS_SIGNED_(type) (((type)0)>((type)-1))
|
||||
( (type) ((( ((type) 1) << (sizeof(type) * 8 - 2)) - 1) * 2 + 1) )
|
||||
#define MHD_TYPE_IS_SIGNED_(type) (((type) 0)>((type) - 1))
|
||||
|
||||
#ifndef UINT_MAX
|
||||
#ifdef __UINT_MAX__
|
||||
#define UINT_MAX __UINT_MAX__
|
||||
#else /* ! __UINT_MAX__ */
|
||||
#define UINT_MAX MHD_UNSIGNED_TYPE_MAX_(unsigned int)
|
||||
#define UINT_MAX MHD_UNSIGNED_TYPE_MAX_ (unsigned int)
|
||||
#endif /* ! __UINT_MAX__ */
|
||||
#endif /* !UINT_MAX */
|
||||
|
||||
@@ -50,19 +50,19 @@
|
||||
#ifdef __LONG_MAX__
|
||||
#define LONG_MAX __LONG_MAX__
|
||||
#else /* ! __LONG_MAX__ */
|
||||
#define LONG_MAX MHD_SIGNED_TYPE_MAX(long)
|
||||
#define LONG_MAX MHD_SIGNED_TYPE_MAX (long)
|
||||
#endif /* ! __LONG_MAX__ */
|
||||
#endif /* !OFF_T_MAX */
|
||||
|
||||
#ifndef ULLONG_MAX
|
||||
#define ULLONG_MAX MHD_UNSIGNED_TYPE_MAX_(MHD_UNSIGNED_LONG_LONG)
|
||||
#define ULLONG_MAX MHD_UNSIGNED_TYPE_MAX_ (MHD_UNSIGNED_LONG_LONG)
|
||||
#endif /* !ULLONG_MAX */
|
||||
|
||||
#ifndef INT32_MAX
|
||||
#ifdef __INT32_MAX__
|
||||
#define INT32_MAX __INT32_MAX__
|
||||
#else /* ! __INT32_MAX__ */
|
||||
#define INT32_MAX ((int32_t)0x7FFFFFFF)
|
||||
#define INT32_MAX ((int32_t) 0x7FFFFFFF)
|
||||
#endif /* ! __INT32_MAX__ */
|
||||
#endif /* !INT32_MAX */
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
#ifdef __UINT32_MAX__
|
||||
#define UINT32_MAX __UINT32_MAX__
|
||||
#else /* ! __UINT32_MAX__ */
|
||||
#define UINT32_MAX ((int32_t)0xFFFFFFFF)
|
||||
#define UINT32_MAX ((int32_t) 0xFFFFFFFF)
|
||||
#endif /* ! __UINT32_MAX__ */
|
||||
#endif /* !UINT32_MAX */
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
#ifdef __UINT64_MAX__
|
||||
#define UINT64_MAX __UINT64_MAX__
|
||||
#else /* ! __UINT64_MAX__ */
|
||||
#define UINT64_MAX ((uint64_t)0xFFFFFFFFFFFFFFFF)
|
||||
#define UINT64_MAX ((uint64_t) 0xFFFFFFFFFFFFFFFF)
|
||||
#endif /* ! __UINT64_MAX__ */
|
||||
#endif /* !UINT64_MAX */
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
#ifdef __INT64_MAX__
|
||||
#define INT64_MAX __INT64_MAX__
|
||||
#else /* ! __INT64_MAX__ */
|
||||
#define INT64_MAX ((int64_t)0x7FFFFFFFFFFFFFFF)
|
||||
#define INT64_MAX ((int64_t) 0x7FFFFFFFFFFFFFFF)
|
||||
#endif /* ! __UINT64_MAX__ */
|
||||
#endif /* !INT64_MAX */
|
||||
|
||||
@@ -96,8 +96,8 @@
|
||||
#elif defined(UINTPTR_MAX)
|
||||
#define SIZE_MAX UINTPTR_MAX
|
||||
#else /* ! __SIZE_MAX__ */
|
||||
#define SIZE_MAX MHD_UNSIGNED_TYPE_MAX_(size_t)
|
||||
#endif /* ! __SIZE_MAX__ */
|
||||
#define SIZE_MAX MHD_UNSIGNED_TYPE_MAX_ (size_t)
|
||||
#endif /* ! __SIZE_MAX__ */
|
||||
#endif /* !SIZE_MAX */
|
||||
|
||||
#ifndef SSIZE_MAX
|
||||
@@ -108,7 +108,7 @@
|
||||
#elif defined(INTPTR_MAX)
|
||||
#define SSIZE_MAX INTPTR_MAX
|
||||
#else
|
||||
#define SSIZE_MAN MHD_SIGNED_TYPE_MAX_(ssize_t)
|
||||
#define SSIZE_MAN MHD_SIGNED_TYPE_MAX_ (ssize_t)
|
||||
#endif
|
||||
#endif /* ! SSIZE_MAX */
|
||||
|
||||
@@ -120,19 +120,19 @@
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
#define OFF_T_MAX INT64_MAX
|
||||
#else
|
||||
#define OFF_T_MAX MHD_SIGNED_TYPE_MAX_(off_t)
|
||||
#define OFF_T_MAX MHD_SIGNED_TYPE_MAX_ (off_t)
|
||||
#endif
|
||||
#endif /* !OFF_T_MAX */
|
||||
|
||||
#if defined(_LARGEFILE64_SOURCE) && !defined(OFF64_T_MAX)
|
||||
#define OFF64_T_MAX MHD_SIGNED_TYPE_MAX_(uint64_t)
|
||||
#if defined(_LARGEFILE64_SOURCE) && ! defined(OFF64_T_MAX)
|
||||
#define OFF64_T_MAX MHD_SIGNED_TYPE_MAX_ (uint64_t)
|
||||
#endif /* _LARGEFILE64_SOURCE && !OFF64_T_MAX */
|
||||
|
||||
#ifndef TIME_T_MAX
|
||||
#define TIME_T_MAX ((time_t) \
|
||||
( MHD_TYPE_IS_SIGNED_(time_t) ? \
|
||||
MHD_SIGNED_TYPE_MAX_(time_t) : \
|
||||
MHD_UNSIGNED_TYPE_MAX_(time_t)))
|
||||
(MHD_TYPE_IS_SIGNED_ (time_t) ? \
|
||||
MHD_SIGNED_TYPE_MAX_ (time_t) : \
|
||||
MHD_UNSIGNED_TYPE_MAX_ (time_t)))
|
||||
#endif /* !TIME_T_MAX */
|
||||
|
||||
#ifndef TIMEVAL_TV_SEC_MAX
|
||||
|
||||
+25
-22
@@ -59,14 +59,15 @@
|
||||
# include <stdlib.h>
|
||||
/* Simple implementation of MHD_PANIC, to be used outside lib */
|
||||
# define MHD_PANIC(msg) do { fprintf (stderr, \
|
||||
"Abnormal termination at %d line in file %s: %s\n", \
|
||||
(int)__LINE__, __FILE__, msg); abort();} while(0)
|
||||
"Abnormal termination at %d line in file %s: %s\n", \
|
||||
(int) __LINE__, __FILE__, msg); abort (); \
|
||||
} while (0)
|
||||
#endif /* ! MHD_PANIC */
|
||||
|
||||
#if defined(MHD_PTHREAD_MUTEX_)
|
||||
typedef pthread_mutex_t MHD_mutex_;
|
||||
typedef pthread_mutex_t MHD_mutex_;
|
||||
#elif defined(MHD_W32_MUTEX_)
|
||||
typedef CRITICAL_SECTION MHD_mutex_;
|
||||
typedef CRITICAL_SECTION MHD_mutex_;
|
||||
#endif
|
||||
|
||||
#if defined(MHD_PTHREAD_MUTEX_)
|
||||
@@ -75,14 +76,15 @@
|
||||
* @param pmutex pointer to the mutex
|
||||
* @return nonzero on success, zero otherwise
|
||||
*/
|
||||
#define MHD_mutex_init_(pmutex) (!(pthread_mutex_init((pmutex), NULL)))
|
||||
#define MHD_mutex_init_(pmutex) (! (pthread_mutex_init ((pmutex), NULL)))
|
||||
#elif defined(MHD_W32_MUTEX_)
|
||||
/**
|
||||
* Initialise new mutex.
|
||||
* @param pmutex pointer to mutex
|
||||
* @return nonzero on success, zero otherwise
|
||||
*/
|
||||
#define MHD_mutex_init_(pmutex) (InitializeCriticalSectionAndSpinCount((pmutex),16))
|
||||
#define MHD_mutex_init_(pmutex) (InitializeCriticalSectionAndSpinCount ( \
|
||||
(pmutex),16))
|
||||
#endif
|
||||
|
||||
#if defined(MHD_PTHREAD_MUTEX_)
|
||||
@@ -90,7 +92,8 @@
|
||||
/**
|
||||
* Define static mutex and statically initialise it.
|
||||
*/
|
||||
# define MHD_MUTEX_STATIC_DEFN_INIT_(m) static MHD_mutex_ m = PTHREAD_MUTEX_INITIALIZER
|
||||
# define MHD_MUTEX_STATIC_DEFN_INIT_(m) static MHD_mutex_ m = \
|
||||
PTHREAD_MUTEX_INITIALIZER
|
||||
# endif /* PTHREAD_MUTEX_INITIALIZER */
|
||||
#endif
|
||||
|
||||
@@ -100,14 +103,14 @@
|
||||
* @param pmutex pointer to mutex
|
||||
* @return nonzero on success, zero otherwise
|
||||
*/
|
||||
#define MHD_mutex_destroy_(pmutex) (!(pthread_mutex_destroy((pmutex))))
|
||||
#define MHD_mutex_destroy_(pmutex) (! (pthread_mutex_destroy ((pmutex))))
|
||||
#elif defined(MHD_W32_MUTEX_)
|
||||
/**
|
||||
* Destroy previously initialised mutex.
|
||||
* @param pmutex pointer to mutex
|
||||
* @return Always nonzero
|
||||
*/
|
||||
#define MHD_mutex_destroy_(pmutex) (DeleteCriticalSection((pmutex)), !0)
|
||||
#define MHD_mutex_destroy_(pmutex) (DeleteCriticalSection ((pmutex)), ! 0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -116,9 +119,9 @@
|
||||
* @param pmutex pointer to mutex
|
||||
*/
|
||||
#define MHD_mutex_destroy_chk_(pmutex) do { \
|
||||
if (!MHD_mutex_destroy_(pmutex)) \
|
||||
MHD_PANIC(_("Failed to destroy mutex.\n")); \
|
||||
} while(0)
|
||||
if (! MHD_mutex_destroy_ (pmutex)) \
|
||||
MHD_PANIC (_ ("Failed to destroy mutex.\n")); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#if defined(MHD_PTHREAD_MUTEX_)
|
||||
@@ -129,7 +132,7 @@
|
||||
* @param pmutex pointer to mutex
|
||||
* @return nonzero on success, zero otherwise
|
||||
*/
|
||||
#define MHD_mutex_lock_(pmutex) (!(pthread_mutex_lock((pmutex))))
|
||||
#define MHD_mutex_lock_(pmutex) (! (pthread_mutex_lock ((pmutex))))
|
||||
#elif defined(MHD_W32_MUTEX_)
|
||||
/**
|
||||
* Acquire lock on previously initialised mutex.
|
||||
@@ -138,7 +141,7 @@
|
||||
* @param pmutex pointer to mutex
|
||||
* @return Always nonzero
|
||||
*/
|
||||
#define MHD_mutex_lock_(pmutex) (EnterCriticalSection((pmutex)), !0)
|
||||
#define MHD_mutex_lock_(pmutex) (EnterCriticalSection ((pmutex)), ! 0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -149,9 +152,9 @@
|
||||
* @param pmutex pointer to mutex
|
||||
*/
|
||||
#define MHD_mutex_lock_chk_(pmutex) do { \
|
||||
if (!MHD_mutex_lock_(pmutex)) \
|
||||
MHD_PANIC(_("Failed to lock mutex.\n")); \
|
||||
} while(0)
|
||||
if (! MHD_mutex_lock_ (pmutex)) \
|
||||
MHD_PANIC (_ ("Failed to lock mutex.\n")); \
|
||||
} while (0)
|
||||
|
||||
#if defined(MHD_PTHREAD_MUTEX_)
|
||||
/**
|
||||
@@ -159,14 +162,14 @@
|
||||
* @param pmutex pointer to mutex
|
||||
* @return nonzero on success, zero otherwise
|
||||
*/
|
||||
#define MHD_mutex_unlock_(pmutex) (!(pthread_mutex_unlock((pmutex))))
|
||||
#define MHD_mutex_unlock_(pmutex) (! (pthread_mutex_unlock ((pmutex))))
|
||||
#elif defined(MHD_W32_MUTEX_)
|
||||
/**
|
||||
* Unlock previously initialised and locked mutex.
|
||||
* @param pmutex pointer to mutex
|
||||
* @return Always nonzero
|
||||
*/
|
||||
#define MHD_mutex_unlock_(pmutex) (LeaveCriticalSection((pmutex)), !0)
|
||||
#define MHD_mutex_unlock_(pmutex) (LeaveCriticalSection ((pmutex)), ! 0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -175,9 +178,9 @@
|
||||
* @param pmutex pointer to mutex
|
||||
*/
|
||||
#define MHD_mutex_unlock_chk_(pmutex) do { \
|
||||
if (!MHD_mutex_unlock_(pmutex)) \
|
||||
MHD_PANIC(_("Failed to unlock mutex.\n")); \
|
||||
} while(0)
|
||||
if (! MHD_mutex_unlock_ (pmutex)) \
|
||||
MHD_PANIC (_ ("Failed to unlock mutex.\n")); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#endif /* ! MHD_LOCKS_H */
|
||||
|
||||
+89
-87
@@ -76,7 +76,8 @@ static clockid_t mono_clock_id = _MHD_UNWANTED_CLOCK;
|
||||
#endif /* HAVE_CLOCK_GETTIME */
|
||||
|
||||
/* sync clocks; reduce chance of value wrap */
|
||||
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_GET_TIME) || defined(HAVE_GETHRTIME)
|
||||
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_GET_TIME) || \
|
||||
defined(HAVE_GETHRTIME)
|
||||
static time_t mono_clock_start;
|
||||
#endif /* HAVE_CLOCK_GETTIME || HAVE_CLOCK_GET_TIME || HAVE_GETHRTIME */
|
||||
static time_t sys_clock_start;
|
||||
@@ -124,9 +125,9 @@ enum _MHD_mono_clock_source
|
||||
*/
|
||||
_MHD_CLOCK_GETTICKCOUNT64,
|
||||
|
||||
/**
|
||||
* QueryPerformanceCounter() / QueryPerformanceFrequency()
|
||||
*/
|
||||
/**
|
||||
* QueryPerformanceCounter() / QueryPerformanceFrequency()
|
||||
*/
|
||||
_MHD_CLOCK_PERFCOUNTER
|
||||
};
|
||||
|
||||
@@ -153,8 +154,8 @@ MHD_monotonic_sec_counter_init (void)
|
||||
/* just a little syntactic trick to get the
|
||||
various following ifdef's to work out nicely */
|
||||
if (0)
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
else
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
#ifdef CLOCK_MONOTONIC_COARSE
|
||||
@@ -163,11 +164,11 @@ MHD_monotonic_sec_counter_init (void)
|
||||
/* but preferred since it's fast */
|
||||
if (0 == clock_gettime (CLOCK_MONOTONIC_COARSE,
|
||||
&ts))
|
||||
{
|
||||
mono_clock_id = CLOCK_MONOTONIC_COARSE;
|
||||
mono_clock_start = ts.tv_sec;
|
||||
mono_clock_source = _MHD_CLOCK_GETTIME;
|
||||
}
|
||||
{
|
||||
mono_clock_id = CLOCK_MONOTONIC_COARSE;
|
||||
mono_clock_start = ts.tv_sec;
|
||||
mono_clock_source = _MHD_CLOCK_GETTIME;
|
||||
}
|
||||
else
|
||||
#endif /* CLOCK_MONOTONIC_COARSE */
|
||||
#ifdef CLOCK_MONOTONIC_FAST
|
||||
@@ -175,11 +176,11 @@ MHD_monotonic_sec_counter_init (void)
|
||||
/* Can be affected by frequency adjustment, but preferred since it's fast */
|
||||
if (0 == clock_gettime (CLOCK_MONOTONIC_FAST,
|
||||
&ts))
|
||||
{
|
||||
mono_clock_id = CLOCK_MONOTONIC_FAST;
|
||||
mono_clock_start = ts.tv_sec;
|
||||
mono_clock_source = _MHD_CLOCK_GETTIME;
|
||||
}
|
||||
{
|
||||
mono_clock_id = CLOCK_MONOTONIC_FAST;
|
||||
mono_clock_start = ts.tv_sec;
|
||||
mono_clock_source = _MHD_CLOCK_GETTIME;
|
||||
}
|
||||
else
|
||||
#endif /* CLOCK_MONOTONIC_COARSE */
|
||||
#ifdef CLOCK_MONOTONIC_RAW
|
||||
@@ -187,11 +188,11 @@ MHD_monotonic_sec_counter_init (void)
|
||||
/* Not affected by frequency adjustment, but don't count time in suspend */
|
||||
if (0 == clock_gettime (CLOCK_MONOTONIC_RAW,
|
||||
&ts))
|
||||
{
|
||||
mono_clock_id = CLOCK_MONOTONIC_RAW;
|
||||
mono_clock_start = ts.tv_sec;
|
||||
mono_clock_source = _MHD_CLOCK_GETTIME;
|
||||
}
|
||||
{
|
||||
mono_clock_id = CLOCK_MONOTONIC_RAW;
|
||||
mono_clock_start = ts.tv_sec;
|
||||
mono_clock_source = _MHD_CLOCK_GETTIME;
|
||||
}
|
||||
else
|
||||
#endif /* CLOCK_MONOTONIC_RAW */
|
||||
#ifdef CLOCK_BOOTTIME
|
||||
@@ -200,11 +201,11 @@ MHD_monotonic_sec_counter_init (void)
|
||||
/* but can be slower value-getting than other clocks */
|
||||
if (0 == clock_gettime (CLOCK_BOOTTIME,
|
||||
&ts))
|
||||
{
|
||||
mono_clock_id = CLOCK_BOOTTIME;
|
||||
mono_clock_start = ts.tv_sec;
|
||||
mono_clock_source = _MHD_CLOCK_GETTIME;
|
||||
}
|
||||
{
|
||||
mono_clock_id = CLOCK_BOOTTIME;
|
||||
mono_clock_start = ts.tv_sec;
|
||||
mono_clock_source = _MHD_CLOCK_GETTIME;
|
||||
}
|
||||
else
|
||||
#endif /* CLOCK_BOOTTIME */
|
||||
#ifdef CLOCK_MONOTONIC
|
||||
@@ -213,11 +214,11 @@ MHD_monotonic_sec_counter_init (void)
|
||||
/* On Linux it's not truly monotonic as it doesn't count time in suspend */
|
||||
if (0 == clock_gettime (CLOCK_MONOTONIC,
|
||||
&ts))
|
||||
{
|
||||
mono_clock_id = CLOCK_MONOTONIC;
|
||||
mono_clock_start = ts.tv_sec;
|
||||
mono_clock_source = _MHD_CLOCK_GETTIME;
|
||||
}
|
||||
{
|
||||
mono_clock_id = CLOCK_MONOTONIC;
|
||||
mono_clock_start = ts.tv_sec;
|
||||
mono_clock_source = _MHD_CLOCK_GETTIME;
|
||||
}
|
||||
else
|
||||
#endif /* CLOCK_BOOTTIME */
|
||||
#endif /* HAVE_CLOCK_GETTIME */
|
||||
@@ -225,15 +226,15 @@ MHD_monotonic_sec_counter_init (void)
|
||||
/* Darwin-specific monotonic clock */
|
||||
/* Should be monotonic as clock_set_time function always unconditionally */
|
||||
/* failed on latest kernels */
|
||||
if ( (KERN_SUCCESS == host_get_clock_service (mach_host_self(),
|
||||
if ( (KERN_SUCCESS == host_get_clock_service (mach_host_self (),
|
||||
SYSTEM_CLOCK,
|
||||
&mono_clock_service)) &&
|
||||
(KERN_SUCCESS == clock_get_time (mono_clock_service,
|
||||
&cur_time)) )
|
||||
{
|
||||
mono_clock_start = cur_time.tv_sec;
|
||||
mono_clock_source = _MHD_CLOCK_GET_TIME;
|
||||
}
|
||||
{
|
||||
mono_clock_start = cur_time.tv_sec;
|
||||
mono_clock_source = _MHD_CLOCK_GET_TIME;
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_CLOCK_GET_TIME */
|
||||
#ifdef _WIN32
|
||||
@@ -241,25 +242,25 @@ MHD_monotonic_sec_counter_init (void)
|
||||
/* W32 Vista or later specific monotonic clock */
|
||||
/* Available since Vista, ~15ms accuracy */
|
||||
if (1)
|
||||
{
|
||||
tick_start = GetTickCount64 ();
|
||||
mono_clock_source = _MHD_CLOCK_GETTICKCOUNT64;
|
||||
}
|
||||
{
|
||||
tick_start = GetTickCount64 ();
|
||||
mono_clock_source = _MHD_CLOCK_GETTICKCOUNT64;
|
||||
}
|
||||
else
|
||||
#else /* _WIN32_WINNT < 0x0600 */
|
||||
/* W32 specific monotonic clock */
|
||||
/* Available on Windows 2000 and later */
|
||||
if (1)
|
||||
{
|
||||
LARGE_INTEGER freq;
|
||||
LARGE_INTEGER perf_counter;
|
||||
{
|
||||
LARGE_INTEGER freq;
|
||||
LARGE_INTEGER perf_counter;
|
||||
|
||||
QueryPerformanceFrequency (&freq); /* never fail on XP and later */
|
||||
QueryPerformanceCounter (&perf_counter); /* never fail on XP and later */
|
||||
perf_freq = freq.QuadPart;
|
||||
perf_start = perf_counter.QuadPart;
|
||||
mono_clock_source = _MHD_CLOCK_PERFCOUNTER;
|
||||
}
|
||||
QueryPerformanceFrequency (&freq); /* never fail on XP and later */
|
||||
QueryPerformanceCounter (&perf_counter); /* never fail on XP and later */
|
||||
perf_freq = freq.QuadPart;
|
||||
perf_start = perf_counter.QuadPart;
|
||||
mono_clock_source = _MHD_CLOCK_PERFCOUNTER;
|
||||
}
|
||||
else
|
||||
#endif /* _WIN32_WINNT < 0x0600 */
|
||||
#endif /* _WIN32 */
|
||||
@@ -269,11 +270,11 @@ MHD_monotonic_sec_counter_init (void)
|
||||
/* Not preferred due to be potentially resource-hungry */
|
||||
if (0 == clock_gettime (CLOCK_HIGHRES,
|
||||
&ts))
|
||||
{
|
||||
mono_clock_id = CLOCK_HIGHRES;
|
||||
mono_clock_start = ts.tv_sec;
|
||||
mono_clock_source = _MHD_CLOCK_GETTIME;
|
||||
}
|
||||
{
|
||||
mono_clock_id = CLOCK_HIGHRES;
|
||||
mono_clock_start = ts.tv_sec;
|
||||
mono_clock_source = _MHD_CLOCK_GETTIME;
|
||||
}
|
||||
else
|
||||
#endif /* CLOCK_HIGHRES */
|
||||
#endif /* HAVE_CLOCK_GETTIME */
|
||||
@@ -281,26 +282,26 @@ MHD_monotonic_sec_counter_init (void)
|
||||
/* HP-UX and Solaris monotonic clock */
|
||||
/* Not preferred due to be potentially resource-hungry */
|
||||
if (1)
|
||||
{
|
||||
hrtime_start = gethrtime ();
|
||||
mono_clock_source = _MHD_CLOCK_GETHRTIME;
|
||||
}
|
||||
{
|
||||
hrtime_start = gethrtime ();
|
||||
mono_clock_source = _MHD_CLOCK_GETHRTIME;
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_GETHRTIME */
|
||||
{
|
||||
/* no suitable clock source was found */
|
||||
mono_clock_source = _MHD_CLOCK_NO_SOURCE;
|
||||
}
|
||||
{
|
||||
/* no suitable clock source was found */
|
||||
mono_clock_source = _MHD_CLOCK_NO_SOURCE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CLOCK_GET_TIME
|
||||
if ( (_MHD_CLOCK_GET_TIME != mono_clock_source) &&
|
||||
(_MHD_INVALID_CLOCK_SERV != mono_clock_service) )
|
||||
{
|
||||
/* clock service was initialised but clock_get_time failed */
|
||||
mach_port_deallocate (mach_task_self(),
|
||||
mono_clock_service);
|
||||
mono_clock_service = _MHD_INVALID_CLOCK_SERV;
|
||||
}
|
||||
{
|
||||
/* clock service was initialised but clock_get_time failed */
|
||||
mach_port_deallocate (mach_task_self (),
|
||||
mono_clock_service);
|
||||
mono_clock_service = _MHD_INVALID_CLOCK_SERV;
|
||||
}
|
||||
#else
|
||||
(void) mono_clock_source; /* avoid compiler warning */
|
||||
#endif /* HAVE_CLOCK_GET_TIME */
|
||||
@@ -317,11 +318,11 @@ MHD_monotonic_sec_counter_finish (void)
|
||||
{
|
||||
#ifdef HAVE_CLOCK_GET_TIME
|
||||
if (_MHD_INVALID_CLOCK_SERV != mono_clock_service)
|
||||
{
|
||||
mach_port_deallocate (mach_task_self(),
|
||||
mono_clock_service);
|
||||
mono_clock_service = _MHD_INVALID_CLOCK_SERV;
|
||||
}
|
||||
{
|
||||
mach_port_deallocate (mach_task_self (),
|
||||
mono_clock_service);
|
||||
mono_clock_service = _MHD_INVALID_CLOCK_SERV;
|
||||
}
|
||||
#endif /* HAVE_CLOCK_GET_TIME */
|
||||
}
|
||||
|
||||
@@ -340,37 +341,38 @@ MHD_monotonic_sec_counter (void)
|
||||
struct timespec ts;
|
||||
|
||||
if ( (_MHD_UNWANTED_CLOCK != mono_clock_id) &&
|
||||
(0 == clock_gettime (mono_clock_id ,
|
||||
(0 == clock_gettime (mono_clock_id,
|
||||
&ts)) )
|
||||
return ts.tv_sec - mono_clock_start;
|
||||
#endif /* HAVE_CLOCK_GETTIME */
|
||||
#ifdef HAVE_CLOCK_GET_TIME
|
||||
if (_MHD_INVALID_CLOCK_SERV != mono_clock_service)
|
||||
{
|
||||
mach_timespec_t cur_time;
|
||||
{
|
||||
mach_timespec_t cur_time;
|
||||
|
||||
if (KERN_SUCCESS == clock_get_time(mono_clock_service,
|
||||
&cur_time))
|
||||
return cur_time.tv_sec - mono_clock_start;
|
||||
}
|
||||
if (KERN_SUCCESS == clock_get_time (mono_clock_service,
|
||||
&cur_time))
|
||||
return cur_time.tv_sec - mono_clock_start;
|
||||
}
|
||||
#endif /* HAVE_CLOCK_GET_TIME */
|
||||
#if defined(_WIN32)
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
if (1)
|
||||
return (time_t)(((uint64_t)(GetTickCount64() - tick_start)) / 1000);
|
||||
return (time_t) (((uint64_t) (GetTickCount64 () - tick_start)) / 1000);
|
||||
#else /* _WIN32_WINNT < 0x0600 */
|
||||
if (0 != perf_freq)
|
||||
{
|
||||
LARGE_INTEGER perf_counter;
|
||||
{
|
||||
LARGE_INTEGER perf_counter;
|
||||
|
||||
QueryPerformanceCounter (&perf_counter); /* never fail on XP and later */
|
||||
return (time_t)(((uint64_t)(perf_counter.QuadPart - perf_start)) / perf_freq);
|
||||
}
|
||||
QueryPerformanceCounter (&perf_counter); /* never fail on XP and later */
|
||||
return (time_t) (((uint64_t) (perf_counter.QuadPart - perf_start))
|
||||
/ perf_freq);
|
||||
}
|
||||
#endif /* _WIN32_WINNT < 0x0600 */
|
||||
#endif /* _WIN32 */
|
||||
#ifdef HAVE_GETHRTIME
|
||||
if (1)
|
||||
return (time_t)(((uint64_t) (gethrtime () - hrtime_start)) / 1000000000);
|
||||
return (time_t) (((uint64_t) (gethrtime () - hrtime_start)) / 1000000000);
|
||||
#endif /* HAVE_GETHRTIME */
|
||||
|
||||
return time (NULL) - sys_clock_start;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user