Blame src/testcurl/test_quiesce_stream.c

Packit 875988
/*
Packit 875988
     This file is part of libmicrohttpd
Packit 875988
     Copyright (C) 2016 Christian Grothoff
Packit 875988
Packit 875988
     libmicrohttpd is free software; you can redistribute it and/or modify
Packit 875988
     it under the terms of the GNU General Public License as published
Packit 875988
     by the Free Software Foundation; either version 2, or (at your
Packit 875988
     option) any later version.
Packit 875988
Packit 875988
     libmicrohttpd is distributed in the hope that it will be useful, but
Packit 875988
     WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 875988
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 875988
     General Public License for more details.
Packit 875988
Packit 875988
     You should have received a copy of the GNU General Public License
Packit 875988
     along with libmicrohttpd; see the file COPYING.  If not, write to the
Packit 875988
     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit 875988
     Boston, MA 02110-1301, USA.
Packit 875988
*/
Packit 875988
/**
Packit 875988
 * @file test_quiesce_stream.c
Packit 875988
 * @brief  Testcase for libmicrohttpd quiescing
Packit 875988
 * @author Markus Doppelbauer
Packit 875988
 * @author Christian Grothoff
Packit 875988
 * @author Karlson2k (Evgeny Grin)
Packit 875988
 */
Packit 875988
#include "mhd_options.h"
Packit 875988
#include <stdlib.h>
Packit 875988
#include <stdio.h>
Packit 875988
#include <string.h>
Packit 875988
#include <errno.h>
Packit 875988
#include <pthread.h>
Packit 875988
#include <microhttpd.h>
Packit 875988
#ifdef HAVE_UNISTD_H
Packit 875988
#include <unistd.h>
Packit 875988
#elif defined(_WIN32)
Packit 875988
#include <windows.h>
Packit 875988
#define sleep(s) (Sleep((s)*1000), 0)
Packit 875988
#endif /* _WIN32 */
Packit 875988
Packit 875988
Packit 875988
static volatile unsigned int request_counter;
Packit 875988
Packit 875988
Packit 875988
static void
Packit 875988
http_PanicCallback (void *cls,
Packit 875988
                    const char *file,
Packit 875988
                    unsigned int line,
Packit 875988
                    const char *reason)
Packit 875988
{
Packit 875988
  (void)cls;    /* Unused. Silent compiler warning. */
Packit 875988
  fprintf( stderr,
Packit 875988
           "PANIC: exit process: %s at %s:%u\n",
Packit 875988
           reason,
Packit 875988
           file,
Packit 875988
           line);
Packit 875988
  exit (EXIT_FAILURE);
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static void *
Packit 875988
resume_connection (void *arg)
Packit 875988
{
Packit 875988
  struct MHD_Connection *connection = arg;
Packit 875988
Packit 875988
  /* fprintf (stderr, "Calling resume\n"); */
Packit 875988
  MHD_resume_connection (connection);
Packit 875988
  return NULL;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static void
Packit 875988
suspend_connection (struct MHD_Connection *connection)
Packit 875988
{
Packit 875988
  pthread_t thread_id;
Packit 875988
Packit 875988
  /* fprintf (stderr, "Calling suspend\n"); */
Packit 875988
  MHD_suspend_connection (connection);
Packit 875988
  int status = pthread_create (&thread_id,
Packit 875988
                               NULL,
Packit 875988
                               &resume_connection,
Packit 875988
                               connection);
Packit 875988
  if (0 != status)
Packit 875988
    {
Packit 875988
      fprintf (stderr,
Packit 875988
               "Could not create thead\n");
Packit 875988
      exit( EXIT_FAILURE );
Packit 875988
    }
Packit 875988
  pthread_detach (thread_id);
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
struct ContentReaderUserdata
Packit 875988
{
Packit 875988
  int bytes_written;
Packit 875988
  struct MHD_Connection *connection;
Packit 875988
};
Packit 875988
Packit 875988
Packit 875988
static ssize_t
Packit 875988
http_ContentReaderCallback (void *cls,
Packit 875988
                            uint64_t pos,
Packit 875988
                            char *buf,
Packit 875988
                            size_t max)
Packit 875988
{
Packit 875988
  static const char alphabet[] = "\nABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Packit 875988
  struct ContentReaderUserdata *userdata = cls;
Packit 875988
  (void)pos;(void)max;  /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  if( userdata->bytes_written >= 1024)
Packit 875988
    {
Packit 875988
      fprintf( stderr,
Packit 875988
               "finish: %d\n",
Packit 875988
               request_counter);
Packit 875988
      return MHD_CONTENT_READER_END_OF_STREAM;
Packit 875988
    }
Packit 875988
  userdata->bytes_written++;
Packit 875988
  buf[0] = alphabet[userdata->bytes_written % (sizeof(alphabet) - 1)];
Packit 875988
  suspend_connection (userdata->connection);
Packit 875988
Packit 875988
  return 1;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
http_AccessHandlerCallback (void *cls,
Packit 875988
                            struct MHD_Connection *connection,
Packit 875988
                            const char *url,
Packit 875988
                            const char *method,
Packit 875988
                            const char *version,
Packit 875988
                            const char *upload_data,
Packit 875988
                            size_t *upload_data_size,
Packit 875988
                            void **con_cls )
Packit 875988
{
Packit 875988
  int ret;
Packit 875988
  (void)cls;(void)url;                          /* Unused. Silent compiler warning. */
Packit 875988
  (void)method;(void)version;(void)upload_data; /* Unused. Silent compiler warning. */
Packit 875988
  (void)upload_data_size;                       /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  /* Never respond on first call */
Packit 875988
  if (NULL == *con_cls)
Packit 875988
  {
Packit 875988
    fprintf (stderr,
Packit 875988
             "start: %d\n",
Packit 875988
              ++request_counter);
Packit 875988
Packit 875988
    struct ContentReaderUserdata *userdata = malloc (sizeof(struct ContentReaderUserdata));
Packit 875988
Packit 875988
    if (NULL == userdata)
Packit 875988
      return MHD_NO;
Packit 875988
    userdata->bytes_written = 0;
Packit 875988
    userdata->connection = connection;
Packit 875988
    *con_cls = userdata;
Packit 875988
    return MHD_YES;
Packit 875988
  }
Packit 875988
Packit 875988
  /* Second call: create response */
Packit 875988
  struct MHD_Response *response
Packit 875988
    = MHD_create_response_from_callback (-1,
Packit 875988
                                         32 * 1024,
Packit 875988
                                         &http_ContentReaderCallback,
Packit 875988
                                         *con_cls,
Packit 875988
                                         NULL);
Packit 875988
  ret = MHD_queue_response (connection,
Packit 875988
                            MHD_HTTP_OK,
Packit 875988
                            response);
Packit 875988
  MHD_destroy_response (response);
Packit 875988
Packit 875988
  suspend_connection (connection);
Packit 875988
  return ret;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
int
Packit 875988
main(void)
Packit 875988
{
Packit 875988
  int port;
Packit 875988
  char command_line[1024];
Packit 875988
Packit 875988
  if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
Packit 875988
    port = 0;
Packit 875988
  else
Packit 875988
    port = 1470;
Packit 875988
Packit 875988
  /* Panic callback */
Packit 875988
  MHD_set_panic_func (&http_PanicCallback,
Packit 875988
                      NULL);
Packit 875988
Packit 875988
  /* Flags */
Packit 875988
  unsigned int daemon_flags
Packit 875988
    = MHD_USE_INTERNAL_POLLING_THREAD
Packit 875988
    | MHD_USE_AUTO
Packit 875988
    | MHD_ALLOW_SUSPEND_RESUME
Packit 875988
    | MHD_USE_ITC;
Packit 875988
Packit 875988
  /* Create daemon */
Packit 875988
  struct MHD_Daemon *daemon = MHD_start_daemon (daemon_flags,
Packit 875988
                                                port,
Packit 875988
                                                NULL,
Packit 875988
                                                NULL,
Packit 875988
                                                &http_AccessHandlerCallback,
Packit 875988
                                                NULL,
Packit 875988
                                                MHD_OPTION_END);
Packit 875988
  if (NULL == daemon)
Packit 875988
    return 1;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (daemon, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (daemon); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  sprintf(command_line, "curl -s http://127.0.0.1:%d", port);
Packit 875988
Packit 875988
  if (0 != system (command_line))
Packit 875988
    {
Packit 875988
      MHD_stop_daemon (daemon);
Packit 875988
      return 1;
Packit 875988
    }
Packit 875988
  /* wait for a request */
Packit 875988
  while (0 == request_counter)
Packit 875988
    (void)sleep (1);
Packit 875988
Packit 875988
  fprintf (stderr,
Packit 875988
           "quiesce\n");
Packit 875988
  MHD_quiesce_daemon (daemon);
Packit 875988
Packit 875988
  /* wait a second */
Packit 875988
  (void)sleep (1);
Packit 875988
Packit 875988
  fprintf (stderr,
Packit 875988
           "stopping daemon\n");
Packit 875988
  MHD_stop_daemon (daemon);
Packit 875988
Packit 875988
  return 0;
Packit 875988
}