Blame src/testcurl/test_post.c

Packit 875988
/*
Packit 875988
     This file is part of libmicrohttpd
Packit 875988
     Copyright (C) 2007 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
/**
Packit 875988
 * @file test_post.c
Packit 875988
 * @brief  Testcase for libmicrohttpd POST operations using URL-encoding
Packit 875988
 * @author Christian Grothoff
Packit 875988
 */
Packit 875988
Packit 875988
#include "MHD_config.h"
Packit 875988
#include "platform.h"
Packit 875988
#include <curl/curl.h>
Packit 875988
#include <microhttpd.h>
Packit 875988
#include <stdlib.h>
Packit 875988
#include <string.h>
Packit 875988
#include <time.h>
Packit 875988
Packit 875988
#ifndef WINDOWS
Packit 875988
#include <unistd.h>
Packit 875988
#endif
Packit 875988
Packit 875988
#ifdef _WIN32
Packit 875988
#ifndef WIN32_LEAN_AND_MEAN
Packit 875988
#define WIN32_LEAN_AND_MEAN 1
Packit 875988
#endif /* !WIN32_LEAN_AND_MEAN */
Packit 875988
#include <windows.h>
Packit 875988
#endif
Packit 875988
Packit 875988
#if defined(CPU_COUNT) && (CPU_COUNT+0) < 2
Packit 875988
#undef CPU_COUNT
Packit 875988
#endif
Packit 875988
#if !defined(CPU_COUNT)
Packit 875988
#define CPU_COUNT 2
Packit 875988
#endif
Packit 875988
Packit 875988
#define POST_DATA "name=daniel&project=curl"
Packit 875988
Packit 875988
static int oneone;
Packit 875988
Packit 875988
struct CBC
Packit 875988
{
Packit 875988
  char *buf;
Packit 875988
  size_t pos;
Packit 875988
  size_t size;
Packit 875988
};
Packit 875988
Packit 875988
Packit 875988
static void
Packit 875988
completed_cb (void *cls,
Packit 875988
	      struct MHD_Connection *connection,
Packit 875988
	      void **con_cls,
Packit 875988
	      enum MHD_RequestTerminationCode toe)
Packit 875988
{
Packit 875988
  struct MHD_PostProcessor *pp = *con_cls;
Packit 875988
  (void)cls;(void)connection;(void)toe; /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  if (NULL != pp)
Packit 875988
    MHD_destroy_post_processor (pp);
Packit 875988
  *con_cls = NULL;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static size_t
Packit 875988
copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
Packit 875988
{
Packit 875988
  struct CBC *cbc = ctx;
Packit 875988
Packit 875988
  if (cbc->pos + size * nmemb > cbc->size)
Packit 875988
    return 0;                   /* overflow */
Packit 875988
  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
Packit 875988
  cbc->pos += size * nmemb;
Packit 875988
  return size * nmemb;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Note that this post_iterator is not perfect
Packit 875988
 * in that it fails to support incremental processing.
Packit 875988
 * (to be fixed in the future)
Packit 875988
 */
Packit 875988
static int
Packit 875988
post_iterator (void *cls,
Packit 875988
               enum MHD_ValueKind kind,
Packit 875988
               const char *key,
Packit 875988
               const char *filename,
Packit 875988
               const char *content_type,
Packit 875988
               const char *transfer_encoding,
Packit 875988
               const char *value, uint64_t off, size_t size)
Packit 875988
{
Packit 875988
  int *eok = cls;
Packit 875988
  (void)kind;(void)filename;(void)content_type; /* Unused. Silent compiler warning. */
Packit 875988
  (void)transfer_encoding;(void)off;            /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  if ((0 == strcasecmp (key, "name")) &&
Packit 875988
      (size == strlen ("daniel")) && (0 == strncmp (value, "daniel", size)))
Packit 875988
    (*eok) |= 1;
Packit 875988
  if ((0 == strcasecmp (key, "project")) &&
Packit 875988
      (size == strlen ("curl")) && (0 == strncmp (value, "curl", size)))
Packit 875988
    (*eok) |= 2;
Packit 875988
  return MHD_YES;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
ahc_echo (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, size_t *upload_data_size,
Packit 875988
          void **unused)
Packit 875988
{
Packit 875988
  static int eok;
Packit 875988
  struct MHD_Response *response;
Packit 875988
  struct MHD_PostProcessor *pp;
Packit 875988
  int ret;
Packit 875988
  (void)cls;(void)version;      /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  if (0 != strcasecmp ("POST", method))
Packit 875988
    {
Packit 875988
      printf ("METHOD: %s\n", method);
Packit 875988
      return MHD_NO;            /* unexpected method */
Packit 875988
    }
Packit 875988
  pp = *unused;
Packit 875988
  if (pp == NULL)
Packit 875988
    {
Packit 875988
      eok = 0;
Packit 875988
      pp = MHD_create_post_processor (connection, 1024, &post_iterator, &eok;;
Packit 875988
      *unused = pp;
Packit 875988
    }
Packit 875988
  MHD_post_process (pp, upload_data, *upload_data_size);
Packit 875988
  if ((eok == 3) && (0 == *upload_data_size))
Packit 875988
    {
Packit 875988
      response = MHD_create_response_from_buffer (strlen (url),
Packit 875988
						  (void *) url,
Packit 875988
						  MHD_RESPMEM_MUST_COPY);
Packit 875988
      ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
Packit 875988
      MHD_destroy_response (response);
Packit 875988
      MHD_destroy_post_processor (pp);
Packit 875988
      *unused = NULL;
Packit 875988
      return ret;
Packit 875988
    }
Packit 875988
  *upload_data_size = 0;
Packit 875988
  return MHD_YES;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
testInternalPost ()
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  CURL *c;
Packit 875988
  char buf[2048];
Packit 875988
  struct CBC cbc;
Packit 875988
  CURLcode errornum;
Packit 875988
  int port;
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
    {
Packit 875988
      port = 1370;
Packit 875988
      if (oneone)
Packit 875988
        port += 10;
Packit 875988
    }
Packit 875988
Packit 875988
  cbc.buf = buf;
Packit 875988
  cbc.size = 2048;
Packit 875988
  cbc.pos = 0;
Packit 875988
  d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
Packit 875988
                        port, NULL, NULL, &ahc_echo, NULL,
Packit 875988
			MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL,
Packit 875988
			MHD_OPTION_END);
Packit 875988
  if (d == NULL)
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 (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  c = curl_easy_init ();
Packit 875988
  curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello_world");
Packit 875988
  curl_easy_setopt (c, CURLOPT_PORT, (long)port);
Packit 875988
  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
Packit 875988
  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
Packit 875988
  curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
Packit 875988
  curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
Packit 875988
  curl_easy_setopt (c, CURLOPT_POST, 1L);
Packit 875988
  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
Packit 875988
  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
Packit 875988
  if (oneone)
Packit 875988
    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Packit 875988
  else
Packit 875988
    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Packit 875988
  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
Packit 875988
  /* NOTE: use of CONNECTTIMEOUT without also
Packit 875988
   *   setting NOSIGNAL results in really weird
Packit 875988
   *   crashes on my system! */
Packit 875988
  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
Packit 875988
  if (CURLE_OK != (errornum = curl_easy_perform (c)))
Packit 875988
    {
Packit 875988
      fprintf (stderr,
Packit 875988
               "curl_easy_perform failed: `%s'\n",
Packit 875988
               curl_easy_strerror (errornum));
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
      MHD_stop_daemon (d);
Packit 875988
      return 2;
Packit 875988
    }
Packit 875988
  curl_easy_cleanup (c);
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  if (cbc.pos != strlen ("/hello_world"))
Packit 875988
    return 4;
Packit 875988
  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
Packit 875988
    return 8;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
static int
Packit 875988
testMultithreadedPost ()
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  CURL *c;
Packit 875988
  char buf[2048];
Packit 875988
  struct CBC cbc;
Packit 875988
  CURLcode errornum;
Packit 875988
  int port;
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
    {
Packit 875988
      port = 1371;
Packit 875988
      if (oneone)
Packit 875988
        port += 10;
Packit 875988
    }
Packit 875988
Packit 875988
  cbc.buf = buf;
Packit 875988
  cbc.size = 2048;
Packit 875988
  cbc.pos = 0;
Packit 875988
  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
Packit 875988
                        port, NULL, NULL, &ahc_echo, NULL,
Packit 875988
			MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL,
Packit 875988
			MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 16;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  c = curl_easy_init ();
Packit 875988
  curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello_world");
Packit 875988
  curl_easy_setopt (c, CURLOPT_PORT, (long)port);
Packit 875988
  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
Packit 875988
  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
Packit 875988
  curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
Packit 875988
  curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
Packit 875988
  curl_easy_setopt (c, CURLOPT_POST, 1L);
Packit 875988
  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
Packit 875988
  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
Packit 875988
  if (oneone)
Packit 875988
    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Packit 875988
  else
Packit 875988
    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Packit 875988
  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
Packit 875988
  /* NOTE: use of CONNECTTIMEOUT without also
Packit 875988
   *   setting NOSIGNAL results in really weird
Packit 875988
   *   crashes on my system! */
Packit 875988
  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
Packit 875988
  if (CURLE_OK != (errornum = curl_easy_perform (c)))
Packit 875988
    {
Packit 875988
      fprintf (stderr,
Packit 875988
               "curl_easy_perform failed: `%s'\n",
Packit 875988
               curl_easy_strerror (errornum));
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
      MHD_stop_daemon (d);
Packit 875988
      return 32;
Packit 875988
    }
Packit 875988
  curl_easy_cleanup (c);
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  if (cbc.pos != strlen ("/hello_world"))
Packit 875988
    return 64;
Packit 875988
  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
Packit 875988
    return 128;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
static int
Packit 875988
testMultithreadedPoolPost ()
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  CURL *c;
Packit 875988
  char buf[2048];
Packit 875988
  struct CBC cbc;
Packit 875988
  CURLcode errornum;
Packit 875988
  int port;
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
    {
Packit 875988
      port = 1372;
Packit 875988
      if (oneone)
Packit 875988
        port += 10;
Packit 875988
    }
Packit 875988
Packit 875988
  cbc.buf = buf;
Packit 875988
  cbc.size = 2048;
Packit 875988
  cbc.pos = 0;
Packit 875988
  d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
Packit 875988
                        port, NULL, NULL, &ahc_echo, NULL,
Packit 875988
                        MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT,
Packit 875988
			MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL,
Packit 875988
			MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 16;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  c = curl_easy_init ();
Packit 875988
  curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello_world");
Packit 875988
  curl_easy_setopt (c, CURLOPT_PORT, (long)port);
Packit 875988
  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
Packit 875988
  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
Packit 875988
  curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
Packit 875988
  curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
Packit 875988
  curl_easy_setopt (c, CURLOPT_POST, 1L);
Packit 875988
  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
Packit 875988
  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
Packit 875988
  if (oneone)
Packit 875988
    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Packit 875988
  else
Packit 875988
    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Packit 875988
  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
Packit 875988
  /* NOTE: use of CONNECTTIMEOUT without also
Packit 875988
   *   setting NOSIGNAL results in really weird
Packit 875988
   *   crashes on my system! */
Packit 875988
  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
Packit 875988
  if (CURLE_OK != (errornum = curl_easy_perform (c)))
Packit 875988
    {
Packit 875988
      fprintf (stderr,
Packit 875988
               "curl_easy_perform failed: `%s'\n",
Packit 875988
               curl_easy_strerror (errornum));
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
      MHD_stop_daemon (d);
Packit 875988
      return 32;
Packit 875988
    }
Packit 875988
  curl_easy_cleanup (c);
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  if (cbc.pos != strlen ("/hello_world"))
Packit 875988
    return 64;
Packit 875988
  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
Packit 875988
    return 128;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
static int
Packit 875988
testExternalPost ()
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  CURL *c;
Packit 875988
  char buf[2048];
Packit 875988
  struct CBC cbc;
Packit 875988
  CURLM *multi;
Packit 875988
  CURLMcode mret;
Packit 875988
  fd_set rs;
Packit 875988
  fd_set ws;
Packit 875988
  fd_set es;
Packit 875988
  MHD_socket maxsock;
Packit 875988
#ifdef MHD_WINSOCK_SOCKETS
Packit 875988
  int maxposixs; /* Max socket number unused on W32 */
Packit 875988
#else  /* MHD_POSIX_SOCKETS */
Packit 875988
#define maxposixs maxsock
Packit 875988
#endif /* MHD_POSIX_SOCKETS */
Packit 875988
  int running;
Packit 875988
  struct CURLMsg *msg;
Packit 875988
  time_t start;
Packit 875988
  struct timeval tv;
Packit 875988
  int port;
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
    {
Packit 875988
      port = 1373;
Packit 875988
      if (oneone)
Packit 875988
        port += 10;
Packit 875988
    }
Packit 875988
Packit 875988
  multi = NULL;
Packit 875988
  cbc.buf = buf;
Packit 875988
  cbc.size = 2048;
Packit 875988
  cbc.pos = 0;
Packit 875988
  d = MHD_start_daemon (MHD_USE_ERROR_LOG,
Packit 875988
                        port, NULL, NULL, &ahc_echo, NULL,
Packit 875988
			MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL,
Packit 875988
			MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 256;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  c = curl_easy_init ();
Packit 875988
  curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello_world");
Packit 875988
  curl_easy_setopt (c, CURLOPT_PORT, (long)port);
Packit 875988
  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
Packit 875988
  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
Packit 875988
  curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
Packit 875988
  curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
Packit 875988
  curl_easy_setopt (c, CURLOPT_POST, 1L);
Packit 875988
  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
Packit 875988
  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
Packit 875988
  if (oneone)
Packit 875988
    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Packit 875988
  else
Packit 875988
    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Packit 875988
  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
Packit 875988
  /* NOTE: use of CONNECTTIMEOUT without also
Packit 875988
   *   setting NOSIGNAL results in really weird
Packit 875988
   *   crashes on my system! */
Packit 875988
  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
Packit 875988
Packit 875988
Packit 875988
  multi = curl_multi_init ();
Packit 875988
  if (multi == NULL)
Packit 875988
    {
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
      MHD_stop_daemon (d);
Packit 875988
      return 512;
Packit 875988
    }
Packit 875988
  mret = curl_multi_add_handle (multi, c);
Packit 875988
  if (mret != CURLM_OK)
Packit 875988
    {
Packit 875988
      curl_multi_cleanup (multi);
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
      MHD_stop_daemon (d);
Packit 875988
      return 1024;
Packit 875988
    }
Packit 875988
  start = time (NULL);
Packit 875988
  while ((time (NULL) - start < 5) && (multi != NULL))
Packit 875988
    {
Packit 875988
      maxsock = MHD_INVALID_SOCKET;
Packit 875988
      maxposixs = -1;
Packit 875988
      FD_ZERO (&rs);
Packit 875988
      FD_ZERO (&ws);
Packit 875988
      FD_ZERO (&es);
Packit 875988
      curl_multi_perform (multi, &running);
Packit 875988
      mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs);
Packit 875988
      if (mret != CURLM_OK)
Packit 875988
        {
Packit 875988
          curl_multi_remove_handle (multi, c);
Packit 875988
          curl_multi_cleanup (multi);
Packit 875988
          curl_easy_cleanup (c);
Packit 875988
          MHD_stop_daemon (d);
Packit 875988
          return 2048;
Packit 875988
        }
Packit 875988
      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxsock))
Packit 875988
        {
Packit 875988
          curl_multi_remove_handle (multi, c);
Packit 875988
          curl_multi_cleanup (multi);
Packit 875988
          curl_easy_cleanup (c);
Packit 875988
          MHD_stop_daemon (d);
Packit 875988
          return 4096;
Packit 875988
        }
Packit 875988
      tv.tv_sec = 0;
Packit 875988
      tv.tv_usec = 1000;
Packit 875988
      if (-1 == select (maxposixs + 1, &rs, &ws, &es, &tv))
Packit 875988
        {
Packit 875988
#ifdef MHD_POSIX_SOCKETS
Packit 875988
          if (EINTR != errno)
Packit 875988
            abort ();
Packit 875988
#else
Packit 875988
          if (WSAEINVAL != WSAGetLastError() || 0 != rs.fd_count || 0 != ws.fd_count || 0 != es.fd_count)
Packit 875988
            abort ();
Packit 875988
          Sleep (1000);
Packit 875988
#endif
Packit 875988
        }
Packit 875988
      curl_multi_perform (multi, &running);
Packit 875988
      if (running == 0)
Packit 875988
        {
Packit 875988
          msg = curl_multi_info_read (multi, &running);
Packit 875988
          if (msg == NULL)
Packit 875988
            break;
Packit 875988
          if (msg->msg == CURLMSG_DONE)
Packit 875988
            {
Packit 875988
              if (msg->data.result != CURLE_OK)
Packit 875988
                printf ("%s failed at %s:%d: `%s'\n",
Packit 875988
                        "curl_multi_perform",
Packit 875988
                        __FILE__,
Packit 875988
                        __LINE__, curl_easy_strerror (msg->data.result));
Packit 875988
              curl_multi_remove_handle (multi, c);
Packit 875988
              curl_multi_cleanup (multi);
Packit 875988
              curl_easy_cleanup (c);
Packit 875988
              c = NULL;
Packit 875988
              multi = NULL;
Packit 875988
            }
Packit 875988
        }      MHD_run (d);
Packit 875988
    }
Packit 875988
  if (multi != NULL)
Packit 875988
    {
Packit 875988
      curl_multi_remove_handle (multi, c);
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
      curl_multi_cleanup (multi);
Packit 875988
    }
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  if (cbc.pos != strlen ("/hello_world"))
Packit 875988
    return 8192;
Packit 875988
  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
Packit 875988
    return 16384;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
ahc_cancel (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, size_t *upload_data_size,
Packit 875988
	    void **unused)
Packit 875988
{
Packit 875988
  struct MHD_Response *response;
Packit 875988
  int ret;
Packit 875988
  (void)cls;(void)url;(void)version;            /* Unused. Silent compiler warning. */
Packit 875988
  (void)upload_data;(void)upload_data_size;     /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  if (0 != strcasecmp ("POST", method))
Packit 875988
    {
Packit 875988
      fprintf (stderr,
Packit 875988
	       "Unexpected method `%s'\n", method);
Packit 875988
      return MHD_NO;
Packit 875988
    }
Packit 875988
Packit 875988
  if (*unused == NULL)
Packit 875988
    {
Packit 875988
      *unused = "wibble";
Packit 875988
      /* We don't want the body. Send a 500. */
Packit 875988
      response = MHD_create_response_from_buffer (0, NULL,
Packit 875988
						  MHD_RESPMEM_PERSISTENT);
Packit 875988
      ret = MHD_queue_response(connection, 500, response);
Packit 875988
      if (ret != MHD_YES)
Packit 875988
	fprintf(stderr, "Failed to queue response\n");
Packit 875988
      MHD_destroy_response(response);
Packit 875988
      return ret;
Packit 875988
    }
Packit 875988
  else
Packit 875988
    {
Packit 875988
      fprintf(stderr,
Packit 875988
	      "In ahc_cancel again. This should not happen.\n");
Packit 875988
      return MHD_NO;
Packit 875988
    }
Packit 875988
}
Packit 875988
Packit 875988
struct CRBC
Packit 875988
{
Packit 875988
  const char *buffer;
Packit 875988
  size_t size;
Packit 875988
  size_t pos;
Packit 875988
};
Packit 875988
Packit 875988
Packit 875988
static size_t
Packit 875988
readBuffer(void *p, size_t size, size_t nmemb, void *opaque)
Packit 875988
{
Packit 875988
  struct CRBC *data = opaque;
Packit 875988
  size_t required = size * nmemb;
Packit 875988
  size_t left = data->size - data->pos;
Packit 875988
Packit 875988
  if (required > left)
Packit 875988
    required = left;
Packit 875988
Packit 875988
  memcpy(p, data->buffer + data->pos, required);
Packit 875988
  data->pos += required;
Packit 875988
Packit 875988
  return required/size;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static size_t
Packit 875988
slowReadBuffer(void *p, size_t size, size_t nmemb, void *opaque)
Packit 875988
{
Packit 875988
  (void)sleep(1);
Packit 875988
  return readBuffer(p, size, nmemb, opaque);
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
#define FLAG_EXPECT_CONTINUE 1
Packit 875988
#define FLAG_CHUNKED 2
Packit 875988
#define FLAG_FORM_DATA 4
Packit 875988
#define FLAG_SLOW_READ 8
Packit 875988
#define FLAG_COUNT 16
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
testMultithreadedPostCancelPart(int flags)
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  CURL *c;
Packit 875988
  char buf[2048];
Packit 875988
  struct CBC cbc;
Packit 875988
  CURLcode errornum;
Packit 875988
  struct curl_slist *headers = NULL;
Packit 875988
  long response_code;
Packit 875988
  CURLcode cc;
Packit 875988
  int result = 0;
Packit 875988
  struct CRBC crbc;
Packit 875988
  int port;
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
    {
Packit 875988
      port = 1374;
Packit 875988
      if (oneone)
Packit 875988
        port += 10;
Packit 875988
    }
Packit 875988
Packit 875988
  /* Don't test features that aren't available with HTTP/1.0 in
Packit 875988
   * HTTP/1.0 mode. */
Packit 875988
  if (!oneone && (flags & (FLAG_EXPECT_CONTINUE | FLAG_CHUNKED)))
Packit 875988
    return 0;
Packit 875988
Packit 875988
  cbc.buf = buf;
Packit 875988
  cbc.size = 2048;
Packit 875988
  cbc.pos = 0;
Packit 875988
  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
Packit 875988
                        port, NULL, NULL, &ahc_cancel, NULL,
Packit 875988
			MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 32768;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
Packit 875988
  crbc.buffer = "Test content";
Packit 875988
  crbc.size = strlen(crbc.buffer);
Packit 875988
  crbc.pos = 0;
Packit 875988
Packit 875988
  c = curl_easy_init ();
Packit 875988
  curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello_world");
Packit 875988
  curl_easy_setopt (c, CURLOPT_PORT, (long)port);
Packit 875988
  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
Packit 875988
  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
Packit 875988
  curl_easy_setopt (c, CURLOPT_READFUNCTION, (flags & FLAG_SLOW_READ) ? &slowReadBuffer : &readBuffer);
Packit 875988
  curl_easy_setopt (c, CURLOPT_READDATA, &crbc);
Packit 875988
  curl_easy_setopt (c, CURLOPT_POSTFIELDS, NULL);
Packit 875988
  curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, crbc.size);
Packit 875988
  curl_easy_setopt (c, CURLOPT_POST, 1L);
Packit 875988
  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
Packit 875988
  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
Packit 875988
  if (oneone)
Packit 875988
    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Packit 875988
  else
Packit 875988
    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Packit 875988
  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
Packit 875988
  /* NOTE: use of CONNECTTIMEOUT without also
Packit 875988
   *   setting NOSIGNAL results in really weird
Packit 875988
   *   crashes on my system! */
Packit 875988
  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
Packit 875988
Packit 875988
  if (flags & FLAG_CHUNKED)
Packit 875988
      headers = curl_slist_append(headers, "Transfer-Encoding: chunked");
Packit 875988
  if (!(flags & FLAG_FORM_DATA))
Packit 875988
  headers = curl_slist_append(headers, "Content-Type: application/octet-stream");
Packit 875988
  if (flags & FLAG_EXPECT_CONTINUE)
Packit 875988
      headers = curl_slist_append(headers, "Expect: 100-Continue");
Packit 875988
  curl_easy_setopt(c, CURLOPT_HTTPHEADER, headers);
Packit 875988
Packit 875988
  if (CURLE_HTTP_RETURNED_ERROR != (errornum = curl_easy_perform (c)))
Packit 875988
    {
Packit 875988
#ifdef _WIN32
Packit 875988
      curl_version_info_data *curlverd = curl_version_info(CURLVERSION_NOW);
Packit 875988
      if (0 != (flags & FLAG_SLOW_READ) && CURLE_RECV_ERROR == errornum &&
Packit 875988
          (curlverd == NULL || curlverd->ares_num < 0x073100) )
Packit 875988
        { /* libcurl up to version 7.49.0 didn't have workaround for WinSock bug */
Packit 875988
          fprintf (stderr, "Ignored curl_easy_perform expected failure on W32 with \"slow read\".\n");
Packit 875988
          result = 0;
Packit 875988
        }
Packit 875988
      else
Packit 875988
#else  /* ! _WIN32 */
Packit 875988
      if(1)
Packit 875988
#endif /* ! _WIN32 */
Packit 875988
        {
Packit 875988
          fprintf (stderr,
Packit 875988
                   "flibbet curl_easy_perform didn't fail as expected: `%s' %d\n",
Packit 875988
                   curl_easy_strerror (errornum), errornum);
Packit 875988
          result = 65536;
Packit 875988
        }
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
      MHD_stop_daemon (d);
Packit 875988
      curl_slist_free_all(headers);
Packit 875988
      return result;
Packit 875988
    }
Packit 875988
Packit 875988
  if (CURLE_OK != (cc = curl_easy_getinfo(c, CURLINFO_RESPONSE_CODE, &response_code)))
Packit 875988
    {
Packit 875988
      fprintf(stderr, "curl_easy_getinfo failed: '%s'\n", curl_easy_strerror(errornum));
Packit 875988
      result = 65536;
Packit 875988
    }
Packit 875988
Packit 875988
  if (!result && (response_code != 500))
Packit 875988
    {
Packit 875988
      fprintf(stderr, "Unexpected response code: %ld\n", response_code);
Packit 875988
      result = 131072;
Packit 875988
    }
Packit 875988
Packit 875988
  if (!result && (cbc.pos != 0))
Packit 875988
    result = 262144;
Packit 875988
Packit 875988
  curl_easy_cleanup (c);
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  curl_slist_free_all(headers);
Packit 875988
  return result;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
testMultithreadedPostCancel()
Packit 875988
{
Packit 875988
  int result = 0;
Packit 875988
  int flags;
Packit 875988
  for(flags = 0; flags < FLAG_COUNT; ++flags)
Packit 875988
    result |= testMultithreadedPostCancelPart(flags);
Packit 875988
  return result;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
int
Packit 875988
main (int argc, char *const *argv)
Packit 875988
{
Packit 875988
  unsigned int errorCount = 0;
Packit 875988
  (void)argc;   /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  oneone = (NULL != strrchr (argv[0], (int) '/')) ?
Packit 875988
    (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
Packit 875988
  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
Packit 875988
    return 2;
Packit 875988
  errorCount += testMultithreadedPostCancel ();
Packit 875988
  errorCount += testInternalPost ();
Packit 875988
  errorCount += testMultithreadedPost ();
Packit 875988
  errorCount += testMultithreadedPoolPost ();
Packit 875988
  errorCount += testExternalPost ();
Packit 875988
  if (errorCount != 0)
Packit 875988
    fprintf (stderr, "Error (code: %u)\n", errorCount);
Packit 875988
  curl_global_cleanup ();
Packit 875988
  return errorCount != 0;       /* 0 == pass */
Packit 875988
}