1748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/*
2748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     This file is part of libmicrohttpd
3748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     Copyright (C) 2007, 2008 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_get_chunked.c
23748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @brief  Testcase for libmicrohttpd GET operations with chunked content encoding
24748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @author Christian Grothoff
25748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
26748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
27748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "MHD_config.h"
28748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "platform.h"
29748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <curl/curl.h>
30748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <microhttpd.h>
31748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <stdlib.h>
32748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <string.h>
33748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <time.h>
34748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
35748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#ifndef WINDOWS
36748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <unistd.h>
37748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
38748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
39748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "socat.c"
40748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
41748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstruct CBC
42748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
43748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char *buf;
44748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t pos;
45748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t size;
46748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat};
47748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
48748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic size_t
49748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratcopyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
50748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
51748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC *cbc = ctx;
52748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
53748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (cbc->pos + size * nmemb > cbc->size)
54748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 0;                   /* overflow */
55748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
56748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc->pos += size * nmemb;
57748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return size * nmemb;
58748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
59748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
60748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
61748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * MHD content reader callback that returns
62748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * data in chunks.
63748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
64748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic ssize_t
65748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratcrc (void *cls, uint64_t pos, char *buf, size_t max)
66748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
67748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Response **responseptr = cls;
68748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
69748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (pos == 128 * 10)
70748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
71748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      MHD_add_response_header (*responseptr, "Footer", "working");
72748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return MHD_CONTENT_READER_END_OF_STREAM;
73748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
74748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (max < 128)
75748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    abort ();                   /* should not happen in this testcase... */
76748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  memset (buf, 'A' + (pos / 128), 128);
77748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 128;
78748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
79748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
80748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
81748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Dummy function that does nothing.
82748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
83748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic void
84748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratcrcf (void *ptr)
85748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
86748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  free (ptr);
87748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
88748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
89748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
90748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratahc_echo (void *cls,
91748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          struct MHD_Connection *connection,
92748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *url,
93748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *method,
94748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *version,
95748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *upload_data, size_t *upload_data_size, void **ptr)
96748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
97748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  static int aptr;
98748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  const char *me = cls;
99748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Response *response;
100748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Response **responseptr;
101748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int ret;
102748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
103748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != strcmp (me, method))
104748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return MHD_NO;              /* unexpected method */
105748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (&aptr != *ptr)
106748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
107748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      /* do never respond on first call */
108748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      *ptr = &aptr;
109748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return MHD_YES;
110748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
111748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  responseptr = malloc (sizeof (struct MHD_Response *));
112748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
113748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                                1024,
114748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                                &crc, responseptr, &crcf);
115748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  *responseptr = response;
116748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
117748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_destroy_response (response);
118748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return ret;
119748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
120748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
121748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
122748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel ErattestInternalGet ()
123748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
124748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Daemon *d;
125748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURL *c;
126748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char buf[2048];
127748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC cbc;
128748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int i;
129748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
130748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.buf = buf;
131748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.size = 2048;
132748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.pos = 0;
133748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
134748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
135748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (d == NULL)
136748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 1;
137748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  zzuf_socat_start ();
138748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  for (i = 0; i < LOOP_COUNT; i++)
139748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
140748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr, ".");
141748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      c = curl_easy_init ();
142748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
143748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
144748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
145748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
146748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
147748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
148748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
149748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      // NOTE: use of CONNECTTIMEOUT without also
150748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      //   setting NOSIGNAL results in really weird
151748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      //   crashes on my system!
152748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
153748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_perform (c);
154748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_cleanup (c);
155748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
156748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fprintf (stderr, "\n");
157748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  zzuf_socat_stop ();
158748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_stop_daemon (d);
159748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
160748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
161748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
162748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
163748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel ErattestMultithreadedGet ()
164748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
165748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Daemon *d;
166748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURL *c;
167748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char buf[2048];
168748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC cbc;
169748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int i;
170748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
171748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.buf = buf;
172748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.size = 2048;
173748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.pos = 0;
174748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ ,
175748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
176748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (d == NULL)
177748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 16;
178748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  zzuf_socat_start ();
179748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  for (i = 0; i < LOOP_COUNT; i++)
180748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
181748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr, ".");
182748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      c = curl_easy_init ();
183748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
184748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
185748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
186748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
187748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
188748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
189748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
190748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      // NOTE: use of CONNECTTIMEOUT without also
191748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      //   setting NOSIGNAL results in really weird
192748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      //   crashes on my system!
193748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
194748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_perform (c);
195748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_cleanup (c);
196748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
197748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fprintf (stderr, "\n");
198748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  zzuf_socat_stop ();
199748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_stop_daemon (d);
200748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
201748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
202748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
203748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
204748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
205748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel ErattestExternalGet ()
206748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
207748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Daemon *d;
208748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURL *c;
209748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char buf[2048];
210748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC cbc;
211748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURLM *multi;
212748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURLMcode mret;
213748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fd_set rs;
214748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fd_set ws;
215748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fd_set es;
216748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int max;
217748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int running;
218748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  time_t start;
219748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct timeval tv;
220748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int i;
221748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
222748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  multi = NULL;
223748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.buf = buf;
224748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.size = 2048;
225748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.pos = 0;
226748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ ,
227748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
228748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (d == NULL)
229748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 256;
230748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  multi = curl_multi_init ();
231748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (multi == NULL)
232748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
233748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      MHD_stop_daemon (d);
234748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return 512;
235748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
236748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  zzuf_socat_start ();
237748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  for (i = 0; i < LOOP_COUNT; i++)
238748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
239748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr, ".");
240748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      c = curl_easy_init ();
241748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
242748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
243748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
244748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
245748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
246748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
247748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
248748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      // NOTE: use of CONNECTTIMEOUT without also
249748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      //   setting NOSIGNAL results in really weird
250748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      //   crashes on my system!
251748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
252748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      mret = curl_multi_add_handle (multi, c);
253748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (mret != CURLM_OK)
254748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
255748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_multi_cleanup (multi);
256748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_cleanup (c);
257748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          zzuf_socat_stop ();
258748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          MHD_stop_daemon (d);
259748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          return 1024;
260748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
261748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      start = time (NULL);
262748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      while ((time (NULL) - start < 5) && (c != NULL))
263748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
264748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          max = 0;
265748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          FD_ZERO (&rs);
266748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          FD_ZERO (&ws);
267748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          FD_ZERO (&es);
268748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_multi_perform (multi, &running);
269748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
270748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (mret != CURLM_OK)
271748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            {
272748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_multi_remove_handle (multi, c);
273748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_multi_cleanup (multi);
274748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_easy_cleanup (c);
275748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              zzuf_socat_stop ();
276748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              MHD_stop_daemon (d);
277748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              return 2048;
278748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            }
279748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
280748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            {
281748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_multi_remove_handle (multi, c);
282748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_multi_cleanup (multi);
283748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_easy_cleanup (c);
284748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              zzuf_socat_stop ();
285748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              MHD_stop_daemon (d);
286748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              return 4096;
287748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            }
288748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          tv.tv_sec = 0;
289748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          tv.tv_usec = 1000;
290748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          select (max + 1, &rs, &ws, &es, &tv);
291748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_multi_perform (multi, &running);
292748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (running == 0)
293748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            {
294748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_multi_info_read (multi, &running);
295748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_multi_remove_handle (multi, c);
296748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_easy_cleanup (c);
297748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              c = NULL;
298748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            }
299748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          MHD_run (d);
300748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
301748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (c != NULL)
302748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
303748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_multi_remove_handle (multi, c);
304748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_cleanup (c);
305748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
306748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
307748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fprintf (stderr, "\n");
308748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_multi_cleanup (multi);
309748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  zzuf_socat_stop ();
310748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_stop_daemon (d);
311748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
312748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
313748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
314748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
315748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
316748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint
317748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratmain (int argc, char *const *argv)
318748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
319748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int errorCount = 0;
320748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
321748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
322748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 2;
323748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  errorCount += testInternalGet ();
324748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  errorCount += testMultithreadedGet ();
325748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  errorCount += testExternalGet ();
326748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (errorCount != 0)
327748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    fprintf (stderr, "Error (code: %u)\n", errorCount);
328748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_global_cleanup ();
329748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return errorCount != 0;       /* 0 == pass */
330748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
331