libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 94ff0707749af6998a051e10e86239d4f8506769
parent d7392e0882eb7b1cc559d25849204c966a5091ef
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri,  4 Nov 2016 21:57:17 +0100

adding test from Markus (adapted by me to C and MHD-style)

Diffstat:
MAUTHORS | 1+
Msrc/testcurl/Makefile.am | 9+++++++++
Asrc/testcurl/test_quiesce_stream.c | 207+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 217 insertions(+), 0 deletions(-)

diff --git a/AUTHORS b/AUTHORS @@ -23,6 +23,7 @@ Matthew Moore Colin Caughie <c.caughie@indigovision.com> David Carvalho <andaris@gmail.com> David Reiss <dreiss@facebook.com> +Markus Doppelbauer <doppelbauer@gmx.net> Matt Holiday Michael Cronenworth <mike@cchtml.com> Milan Straka <straka@ufal.mff.cuni.cz> diff --git a/src/testcurl/Makefile.am b/src/testcurl/Makefile.am @@ -52,6 +52,7 @@ check_PROGRAMS = \ if HAVE_POSIX_THREADS check_PROGRAMS += \ test_quiesce \ + test_quiesce_stream \ test_concurrent_stop \ perf_get_concurrent endif @@ -114,6 +115,14 @@ test_quiesce_LDADD = \ $(top_builddir)/src/microhttpd/libmicrohttpd.la \ $(PTHREAD_LIBS) @LIBCURL@ +test_quiesce_stream_SOURCES = \ + test_quiesce_stream.c +test_quiesce_stream_CFLAGS = \ + $(PTHREAD_CFLAGS) $(AM_CFLAGS) +test_quiesce_stream_LDADD = \ + $(top_builddir)/src/microhttpd/libmicrohttpd.la \ + $(PTHREAD_LIBS) @LIBCURL@ + test_callback_SOURCES = \ test_callback.c test_callback_LDADD = \ diff --git a/src/testcurl/test_quiesce_stream.c b/src/testcurl/test_quiesce_stream.c @@ -0,0 +1,207 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2016 Christian Grothoff + + libmicrohttpd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + libmicrohttpd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libmicrohttpd; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +/** + * @file test_quiesce_stream.c + * @brief Testcase for libmicrohttpd quiescing + * @author Markus Doppelbauer + * @author Christian Grothoff + */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <fcntl.h> +#include <pthread.h> +#include <microhttpd.h> + + +static volatile unsigned int request_counter; + + +static void +http_PanicCallback (void *cls, + const char *file, + unsigned int line, + const char *reason) +{ + fprintf( stderr, + "PANIC: exit process: %s at %s:%u\n", + reason, + file, + line); + exit (EXIT_FAILURE); +} + + +static void * +resume_connection (void *arg) +{ + struct MHD_Connection *connection = arg; + + MHD_resume_connection (connection); + return NULL; +} + + +static void +suspend_connection (struct MHD_Connection *connection) +{ + pthread_t thread_id; + + MHD_suspend_connection (connection); + int status = pthread_create (&thread_id, + NULL, + &resume_connection, + connection); + if (0 != status) + { + fprintf (stderr, + "Could not create thead\n"); + exit( EXIT_FAILURE ); + } + pthread_detach (thread_id); +} + + +struct ContentReaderUserdata +{ + int bytes_written; + struct MHD_Connection *connection; +}; + + +static ssize_t +http_ContentReaderCallback (void *cls, + uint64_t pos, + char *buf, + size_t max) +{ + static const char alphabet[] = "\nABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + struct ContentReaderUserdata *userdata = cls; + + if( userdata->bytes_written >= 1024) + { + fprintf( stderr, + "finish: %d\n", + request_counter); + return MHD_CONTENT_READER_END_OF_STREAM; + } + userdata->bytes_written++; + buf[0] = alphabet[userdata->bytes_written % (sizeof(alphabet) - 1)]; + suspend_connection (userdata->connection); + + return 1; +} + + +static int +http_AccessHandlerCallback (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 ) +{ + int ret; + + /* Never respond on first call */ + if (NULL == *con_cls) + { + fprintf (stderr, + "start: %d\n", + ++request_counter); + + struct ContentReaderUserdata *userdata = malloc (sizeof(struct ContentReaderUserdata)); + + if (NULL == userdata) + return MHD_NO; + userdata->bytes_written = 0; + userdata->connection = connection; + *con_cls = userdata; + return MHD_YES; + } + + /* Second call: create response */ + struct MHD_Response *response + = MHD_create_response_from_callback (-1, + 32 * 1024, + &http_ContentReaderCallback, + *con_cls, + NULL); + ret = MHD_queue_response (connection, + MHD_HTTP_OK, + response); + MHD_destroy_response (response); + + suspend_connection (connection); + return ret; +} + + +int +main() +{ + // Panic callback + MHD_set_panic_func (&http_PanicCallback, + NULL); + + // Flags + unsigned int daemon_flags + = MHD_USE_SELECT_INTERNALLY + | MHD_USE_EPOLL + | MHD_USE_SUSPEND_RESUME + | MHD_USE_PIPE_FOR_SHUTDOWN; + + // Create daemon + struct MHD_Daemon *daemon = MHD_start_daemon (daemon_flags, + 8000, + NULL, + NULL, + &http_AccessHandlerCallback, + NULL, + MHD_OPTION_END); + if (NULL == daemon) + return EXIT_FAILURE; + if (0 != system ("wget --server-response -q -O - 127.0.0.1:8000")) + { + MHD_stop_daemon (daemon); + return EXIT_SUCCESS; + } + // wait for a request + while (0 == request_counter) + sleep (1); + + fprintf (stderr, + "quiesce\n"); + MHD_quiesce_daemon (daemon); + + /* wait a second */ + sleep (1); + + fprintf (stderr, + "stopping daemon\n"); + MHD_stop_daemon (daemon); + + return EXIT_SUCCESS; +}