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 test_iplimit.c
23748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @brief  Testcase for libmicrohttpd GET operations
24748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *         TODO: test parsing of query
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#ifdef _WIN32
41748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#ifndef WIN32_LEAN_AND_MEAN
42748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#define WIN32_LEAN_AND_MEAN 1
43748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif /* !WIN32_LEAN_AND_MEAN */
44748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <windows.h>
45748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
46748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
47748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if defined(CPU_COUNT) && (CPU_COUNT+0) < 2
48748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#undef CPU_COUNT
49748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
50748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if !defined(CPU_COUNT)
51748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#define CPU_COUNT 2
52748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
53748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
54748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int oneone;
55748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
56748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstruct CBC
57748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
58748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char *buf;
59748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t pos;
60748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t size;
61748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat};
62748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
63748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic size_t
64748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratcopyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
65748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
66748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC *cbc = ctx;
67748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
68748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (cbc->pos + size * nmemb > cbc->size)
69748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 0;                   /* overflow */
70748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
71748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc->pos += size * nmemb;
72748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return size * nmemb;
73748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
74748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
75748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
76748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratahc_echo (void *cls,
77748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          struct MHD_Connection *connection,
78748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *url,
79748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *method,
80748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *version,
81748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *upload_data, size_t *upload_data_size,
82748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          void **unused)
83748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
84748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  static int ptr;
85748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  const char *me = cls;
86748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Response *response;
87748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int ret;
88748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
89748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != strcmp (me, method))
90748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return MHD_NO;              /* unexpected method */
91748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (&ptr != *unused)
92748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
93748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      *unused = &ptr;
94748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return MHD_YES;
95748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
96748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  *unused = NULL;
97748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response = MHD_create_response_from_buffer (strlen (url),
98748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat					      (void *) url,
99748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat					      MHD_RESPMEM_MUST_COPY);
100748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
101748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_destroy_response (response);
102748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (ret == MHD_NO)
103748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    abort ();
104748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return ret;
105748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
106748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
107748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
108748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel ErattestMultithreadedGet ()
109748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
110748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Daemon *d;
111748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char buf[2048];
112748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int k;
113748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int success;
114748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int failure;
115748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
116748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /* Test only valid for HTTP/1.1 (uses persistent connections) */
117748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (!oneone)
118748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 0;
119748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
120748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
121748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        1081, NULL, NULL,
122748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        &ahc_echo, "GET",
123748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        MHD_OPTION_PER_IP_CONNECTION_LIMIT, 2,
124748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        MHD_OPTION_END);
125748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (d == NULL)
126748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 16;
127748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
128748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  for (k = 0; k < 3; ++k)
129748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
130748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      struct CBC cbc[3];
131748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      CURL *cenv[3];
132748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      int i;
133748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
134748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      success = 0;
135748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      failure = 0;
136748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      for (i = 0; i < 3; ++i)
137748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
138748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          CURL *c;
139748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          CURLcode errornum;
140748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
141748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          cenv[i] = c = curl_easy_init ();
142748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          cbc[i].buf = buf;
143748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          cbc[i].size = 2048;
144748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          cbc[i].pos = 0;
145748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
146748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1081/hello_world");
147748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
148748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc[i]);
149748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
150748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
151748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_FORBID_REUSE, 0L);
152748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
153748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
154748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          // NOTE: use of CONNECTTIMEOUT without also
155748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          //   setting NOSIGNAL results in really weird
156748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          //   crashes on my system!
157748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
158748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
159748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          errornum = curl_easy_perform (c);
160748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (CURLE_OK == errornum)
161748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            success++;
162748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          else
163748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            failure++;
164748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
165748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
166748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      /* Cleanup the environments */
167748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      for (i = 0; i < 3; ++i)
168748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        curl_easy_cleanup (cenv[i]);
169748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if ( (2 != success) ||
170748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat           (1 != failure) )
171748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      {
172748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        fprintf (stderr,
173748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                 "Unexpected number of success (%u) or failure (%u)\n",
174748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                 success,
175748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                 failure);
176748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        MHD_stop_daemon (d);
177748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        return 32;
178748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      }
179748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
180748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      sleep(2);
181748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
182748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      for (i = 0; i < 2; ++i)
183748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
184748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (cbc[i].pos != strlen ("/hello_world"))
185748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            {
186748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              MHD_stop_daemon (d);
187748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              return 64;
188748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            }
189748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (0 != strncmp ("/hello_world", cbc[i].buf, strlen ("/hello_world")))
190748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            {
191748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              MHD_stop_daemon (d);
192748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              return 128;
193748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            }
194748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
195748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
196748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_stop_daemon (d);
197748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
198748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
199748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
200748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
201748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel ErattestMultithreadedPoolGet ()
202748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
203748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Daemon *d;
204748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char buf[2048];
205748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int k;
206748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
207748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /* Test only valid for HTTP/1.1 (uses persistent connections) */
208748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (!oneone)
209748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 0;
210748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
211748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
212748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        1081, NULL, NULL, &ahc_echo, "GET",
213748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        MHD_OPTION_PER_IP_CONNECTION_LIMIT, 2,
214748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT,
215748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        MHD_OPTION_END);
216748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (d == NULL)
217748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 16;
218748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
219748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  for (k = 0; k < 3; ++k)
220748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
221748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      struct CBC cbc[3];
222748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      CURL *cenv[3];
223748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      int i;
224748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
225748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      for (i = 0; i < 3; ++i)
226748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
227748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          CURL *c;
228748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          CURLcode errornum;
229748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
230748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          cenv[i] = c = curl_easy_init ();
231748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          cbc[i].buf = buf;
232748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          cbc[i].size = 2048;
233748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          cbc[i].pos = 0;
234748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
235748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1081/hello_world");
236748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
237748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc[i]);
238748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
239748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
240748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_FORBID_REUSE, 0L);
241748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
242748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
243748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          // NOTE: use of CONNECTTIMEOUT without also
244748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          //   setting NOSIGNAL results in really weird
245748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          //   crashes on my system!
246748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
247748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
248748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          errornum = curl_easy_perform (c);
249748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if ( ( (CURLE_OK != errornum) && (i <  2) ) ||
250748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat	       ( (CURLE_OK == errornum) && (i == 2) ) )
251748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            {
252748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              int j;
253748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
254748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              /* First 2 should succeed */
255748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              if (i < 2)
256748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                fprintf (stderr,
257748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                         "curl_easy_perform failed: `%s'\n",
258748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                         curl_easy_strerror (errornum));
259748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
260748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              /* Last request should have failed */
261748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              else
262748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                fprintf (stderr,
263748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                         "No error on IP address over limit\n");
264748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
265748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              for (j = 0; j < i; ++j)
266748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                curl_easy_cleanup (cenv[j]);
267748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              MHD_stop_daemon (d);
268748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              return 32;
269748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            }
270748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
271748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
272748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      /* Cleanup the environments */
273748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      for (i = 0; i < 3; ++i)
274748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        curl_easy_cleanup (cenv[i]);
275748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
276748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      sleep(2);
277748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
278748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      for (i = 0; i < 2; ++i)
279748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
280748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (cbc[i].pos != strlen ("/hello_world"))
281748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            {
282748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              MHD_stop_daemon (d);
283748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              return 64;
284748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            }
285748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (0 != strncmp ("/hello_world", cbc[i].buf, strlen ("/hello_world")))
286748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            {
287748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              MHD_stop_daemon (d);
288748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              return 128;
289748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            }
290748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
291748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
292748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
293748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
294748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_stop_daemon (d);
295748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
296748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
297748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
298748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint
299748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratmain (int argc, char *const *argv)
300748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
301748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int errorCount = 0;
302748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
303748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  oneone = (NULL != strrchr (argv[0], (int) '/')) ?
304748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
305748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
306748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 2;
307748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  errorCount |= testMultithreadedGet ();
308748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  errorCount |= testMultithreadedPoolGet ();
309748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (errorCount != 0)
310748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    fprintf (stderr, "Error (code: %u)\n", errorCount);
311748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_global_cleanup ();
312748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return errorCount != 0;       /* 0 == pass */
313748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
314