1748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/*
2748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     This file is part of libmicrohttpd
3748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     Copyright (C) 2007 Christian Grothoff
4748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
5748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     libmicrohttpd is free software; you can redistribute it and/or modify
6748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     it under the terms of the GNU General Public License as published
7748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     by the Free Software Foundation; either version 2, or (at your
8748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     option) any later version.
9748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
10748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     libmicrohttpd is distributed in the hope that it will be useful, but
11748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     WITHOUT ANY WARRANTY; without even the implied warranty of
12748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     General Public License for more details.
14748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
15748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     You should have received a copy of the GNU General Public License
16748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     along with libmicrohttpd; see the file COPYING.  If not, write to the
17748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     Boston, MA 02111-1307, USA.
19748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat*/
20748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
21748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
22748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @file daemontest_put_chunked.c
23748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @brief Testcase for libmicrohttpd PUT operations with chunked encoding
24748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *        for the upload data
25748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @author Christian Grothoff
26748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
27748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
28748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "MHD_config.h"
29748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "platform.h"
30748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <curl/curl.h>
31748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <microhttpd.h>
32748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <stdlib.h>
33748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <string.h>
34748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <time.h>
35748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
36748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#ifndef WINDOWS
37748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <unistd.h>
38748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
39748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
40748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if defined(CPU_COUNT) && (CPU_COUNT+0) < 2
41748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#undef CPU_COUNT
42748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
43748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if !defined(CPU_COUNT)
44748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#define CPU_COUNT 2
45748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
46748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
47748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstruct CBC
48748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
49748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char *buf;
50748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t pos;
51748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t size;
52748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat};
53748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
54748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic size_t
55748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratputBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
56748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
57748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int *pos = ptr;
58748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int wrt;
59748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
60748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  wrt = size * nmemb;
61748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (wrt > 8 - (*pos))
62748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    wrt = 8 - (*pos);
63748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (wrt > 4)
64748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    wrt = 4;                    /* only send half at first => force multiple chunks! */
65748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  memcpy (stream, &("Hello123"[*pos]), wrt);
66748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  (*pos) += wrt;
67748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return wrt;
68748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
69748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
70748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic size_t
71748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratcopyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
72748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
73748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC *cbc = ctx;
74748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
75748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (cbc->pos + size * nmemb > cbc->size)
76748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 0;                   /* overflow */
77748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
78748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc->pos += size * nmemb;
79748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return size * nmemb;
80748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
81748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
82748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
83748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratahc_echo (void *cls,
84748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          struct MHD_Connection *connection,
85748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *url,
86748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *method,
87748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *version,
88748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *upload_data, size_t *upload_data_size,
89748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          void **unused)
90748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
91748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int *done = cls;
92748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Response *response;
93748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int ret;
94748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int have;
95748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
96748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != strcmp ("PUT", method))
97748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return MHD_NO;              /* unexpected method */
98748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if ((*done) < 8)
99748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
100748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      have = *upload_data_size;
101748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (have + *done > 8)
102748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
103748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          printf ("Invalid upload data `%8s'!\n", upload_data);
104748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          return MHD_NO;
105748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
106748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (0 == memcmp (upload_data, &"Hello123"[*done], have))
107748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
108748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          *done += have;
109748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          *upload_data_size = 0;
110748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
111748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      else
112748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
113748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          printf ("Invalid upload data `%8s'!\n", upload_data);
114748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          return MHD_NO;
115748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
116748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if 0
117748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr, "Not ready for response: %u/%u\n", *done, 8);
118748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
119748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return MHD_YES;
120748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
121748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response = MHD_create_response_from_buffer (strlen (url),
122748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat					      (void *) url,
123748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat					      MHD_RESPMEM_MUST_COPY);
124748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
125748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_destroy_response (response);
126748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return ret;
127748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
128748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
129748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
130748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
131748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel ErattestInternalPut ()
132748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
133748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Daemon *d;
134748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURL *c;
135748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char buf[2048];
136748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC cbc;
137748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int pos = 0;
138748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int done_flag = 0;
139748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURLcode errornum;
140748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
141748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.buf = buf;
142748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.size = 2048;
143748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.pos = 0;
144748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
145748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        11080,
146748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
147748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (d == NULL)
148748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 1;
149748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  c = curl_easy_init ();
150748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:11080/hello_world");
151748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
152748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
153748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
154748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
155748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
156748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /*
157748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     // by not giving the file size, we force chunking!
158748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
159748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   */
160748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
161748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
162748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
163748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
164748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  // NOTE: use of CONNECTTIMEOUT without also
165748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //   setting NOSIGNAL results in really weird
166748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //   crashes on my system!
167748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
168748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (CURLE_OK != (errornum = curl_easy_perform (c)))
169748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
170748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr,
171748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               "curl_easy_perform failed: `%s'\n",
172748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               curl_easy_strerror (errornum));
173748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_cleanup (c);
174748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      MHD_stop_daemon (d);
175748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return 2;
176748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
177748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_cleanup (c);
178748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_stop_daemon (d);
179748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (cbc.pos != strlen ("/hello_world"))
180748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 4;
181748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
182748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 8;
183748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
184748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
185748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
186748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
187748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel ErattestMultithreadedPut ()
188748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
189748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Daemon *d;
190748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURL *c;
191748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char buf[2048];
192748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC cbc;
193748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int pos = 0;
194748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int done_flag = 0;
195748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURLcode errornum;
196748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
197748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.buf = buf;
198748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.size = 2048;
199748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.pos = 0;
200748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
201748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        11081,
202748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
203748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (d == NULL)
204748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 16;
205748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  c = curl_easy_init ();
206748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:11081/hello_world");
207748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
208748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
209748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
210748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
211748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
212748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /*
213748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     // by not giving the file size, we force chunking!
214748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
215748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   */
216748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
217748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
218748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
219748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
220748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  // NOTE: use of CONNECTTIMEOUT without also
221748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //   setting NOSIGNAL results in really weird
222748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //   crashes on my system!
223748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
224748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (CURLE_OK != (errornum = curl_easy_perform (c)))
225748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
226748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr,
227748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               "curl_easy_perform failed: `%s'\n",
228748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               curl_easy_strerror (errornum));
229748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_cleanup (c);
230748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      MHD_stop_daemon (d);
231748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return 32;
232748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
233748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_cleanup (c);
234748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_stop_daemon (d);
235748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (cbc.pos != strlen ("/hello_world"))
236748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 64;
237748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
238748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 128;
239748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
240748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
241748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
242748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
243748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
244748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel ErattestMultithreadedPoolPut ()
245748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
246748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Daemon *d;
247748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURL *c;
248748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char buf[2048];
249748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC cbc;
250748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int pos = 0;
251748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int done_flag = 0;
252748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURLcode errornum;
253748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
254748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.buf = buf;
255748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.size = 2048;
256748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.pos = 0;
257748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
258748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        11081,
259748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        NULL, NULL, &ahc_echo, &done_flag,
260748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT, MHD_OPTION_END);
261748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (d == NULL)
262748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 16;
263748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  c = curl_easy_init ();
264748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:11081/hello_world");
265748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
266748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
267748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
268748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
269748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
270748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /*
271748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     // by not giving the file size, we force chunking!
272748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
273748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   */
274748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
275748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
276748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
277748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
278748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  // NOTE: use of CONNECTTIMEOUT without also
279748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //   setting NOSIGNAL results in really weird
280748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //   crashes on my system!
281748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
282748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (CURLE_OK != (errornum = curl_easy_perform (c)))
283748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
284748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr,
285748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               "curl_easy_perform failed: `%s'\n",
286748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               curl_easy_strerror (errornum));
287748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_cleanup (c);
288748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      MHD_stop_daemon (d);
289748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return 32;
290748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
291748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_cleanup (c);
292748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_stop_daemon (d);
293748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (cbc.pos != strlen ("/hello_world"))
294748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 64;
295748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
296748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 128;
297748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
298748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
299748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
300748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
301748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
302748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
303748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel ErattestExternalPut ()
304748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
305748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Daemon *d;
306748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURL *c;
307748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char buf[2048];
308748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC cbc;
309748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURLM *multi;
310748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURLMcode mret;
311748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fd_set rs;
312748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fd_set ws;
313748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fd_set es;
314748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_socket max;
315748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int running;
316748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CURLMsg *msg;
317748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  time_t start;
318748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct timeval tv;
319748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int pos = 0;
320748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int done_flag = 0;
321748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
322748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  multi = NULL;
323748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.buf = buf;
324748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.size = 2048;
325748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.pos = 0;
326748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  d = MHD_start_daemon (MHD_USE_DEBUG,
327748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        11082,
328748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
329748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (d == NULL)
330748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 256;
331748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  c = curl_easy_init ();
332748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:11082/hello_world");
333748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
334748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
335748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
336748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
337748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
338748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /*
339748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     // by not giving the file size, we force chunking!
340748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
341748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   */
342748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
343748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
344748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
345748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
346748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  // NOTE: use of CONNECTTIMEOUT without also
347748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //   setting NOSIGNAL results in really weird
348748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //   crashes on my system!
349748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
350748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
351748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
352748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  multi = curl_multi_init ();
353748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (multi == NULL)
354748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
355748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_cleanup (c);
356748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      MHD_stop_daemon (d);
357748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return 512;
358748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
359748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  mret = curl_multi_add_handle (multi, c);
360748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (mret != CURLM_OK)
361748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
362748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_multi_cleanup (multi);
363748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_cleanup (c);
364748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      MHD_stop_daemon (d);
365748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return 1024;
366748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
367748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  start = time (NULL);
368748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  while ((time (NULL) - start < 5) && (multi != NULL))
369748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
370748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      max = 0;
371748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      FD_ZERO (&rs);
372748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      FD_ZERO (&ws);
373748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      FD_ZERO (&es);
374748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_multi_perform (multi, &running);
375748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
376748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (mret != CURLM_OK)
377748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
378748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_multi_remove_handle (multi, c);
379748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_multi_cleanup (multi);
380748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_cleanup (c);
381748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          MHD_stop_daemon (d);
382748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          return 2048;
383748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
384748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
385748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
386748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_multi_remove_handle (multi, c);
387748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_multi_cleanup (multi);
388748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_cleanup (c);
389748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          MHD_stop_daemon (d);
390748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          return 4096;
391748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
392748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      tv.tv_sec = 0;
393748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      tv.tv_usec = 1000;
394748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      select (max + 1, &rs, &ws, &es, &tv);
395748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_multi_perform (multi, &running);
396748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (running == 0)
397748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
398748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          msg = curl_multi_info_read (multi, &running);
399748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (msg == NULL)
400748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            break;
401748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (msg->msg == CURLMSG_DONE)
402748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            {
403748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              if (msg->data.result != CURLE_OK)
404748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                printf ("%s failed at %s:%d: `%s'\n",
405748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        "curl_multi_perform",
406748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        __FILE__,
407748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        __LINE__, curl_easy_strerror (msg->data.result));
408748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_multi_remove_handle (multi, c);
409748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_multi_cleanup (multi);
410748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_easy_cleanup (c);
411748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              c = NULL;
412748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              multi = NULL;
413748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            }
414748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
415748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      MHD_run (d);
416748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
417748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (multi != NULL)
418748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
419748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_multi_remove_handle (multi, c);
420748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_cleanup (c);
421748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_multi_cleanup (multi);
422748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
423748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_stop_daemon (d);
424748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (cbc.pos != strlen ("/hello_world"))
425748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 8192;
426748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
427748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 16384;
428748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
429748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
430748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
431748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
432748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
433748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint
434748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratmain (int argc, char *const *argv)
435748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
436748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int errorCount = 0;
437748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
438748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
439748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 2;
440748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  errorCount += testInternalPut ();
441748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  errorCount += testMultithreadedPut ();
442748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  errorCount += testMultithreadedPoolPut ();
443748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  errorCount += testExternalPut ();
444748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (errorCount != 0)
445748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    fprintf (stderr, "Error (code: %u)\n", errorCount);
446748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_global_cleanup ();
447748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return errorCount != 0;       /* 0 == pass */
448748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
449