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_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#include "socat.c"
41748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
42748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstruct CBC
43748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
44748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char *buf;
45748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t pos;
46748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t size;
47748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat};
48748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
49748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic size_t
50748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratputBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
51748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
52748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int *pos = ptr;
53748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int wrt;
54748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
55748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  wrt = size * nmemb;
56748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (wrt > 8 - (*pos))
57748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    wrt = 8 - (*pos);
58748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (wrt > 4)
59748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    wrt = 4;                    /* only send half at first => force multiple chunks! */
60748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  memcpy (stream, &("Hello123"[*pos]), wrt);
61748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  (*pos) += wrt;
62748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return wrt;
63748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
64748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
65748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic size_t
66748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratcopyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
67748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
68748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC *cbc = ctx;
69748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
70748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (cbc->pos + size * nmemb > cbc->size)
71748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 0;                   /* overflow */
72748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
73748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc->pos += size * nmemb;
74748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return size * nmemb;
75748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
76748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
77748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
78748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratahc_echo (void *cls,
79748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          struct MHD_Connection *connection,
80748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *url,
81748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *method,
82748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *version,
83748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *upload_data, size_t *upload_data_size,
84748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          void **unused)
85748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
86748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int *done = cls;
87748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Response *response;
88748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int ret;
89748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int have;
90748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
91748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != strcmp ("PUT", method))
92748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return MHD_NO;              /* unexpected method */
93748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if ((*done) < 8)
94748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
95748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      have = *upload_data_size;
96748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (have + *done > 8)
97748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
98748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          return MHD_NO;
99748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
100748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (0 == memcmp (upload_data, &"Hello123"[*done], have))
101748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
102748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          *done += have;
103748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          *upload_data_size = 0;
104748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
105748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      else
106748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
107748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          return MHD_NO;
108748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
109748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if 0
110748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr, "Not ready for response: %u/%u\n", *done, 8);
111748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
112748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return MHD_YES;
113748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
114748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response = MHD_create_response_from_buffer (strlen (url),
115748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat					      (void *) url,
116748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat					      MHD_RESPMEM_MUST_COPY);
117748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
118748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_destroy_response (response);
119748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return ret;
120748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
121748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
122748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
123748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
124748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel ErattestInternalPut ()
125748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
126748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Daemon *d;
127748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURL *c;
128748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char buf[2048];
129748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC cbc;
130748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int pos = 0;
131748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int done_flag = 0;
132748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int i;
133748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
134748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.buf = buf;
135748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.size = 2048;
136748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.pos = 0;
137748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
138748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        11080,
139748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
140748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (d == NULL)
141748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 1;
142748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  zzuf_socat_start ();
143748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  for (i = 0; i < LOOP_COUNT; i++)
144748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
145748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr, ".");
146748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      c = curl_easy_init ();
147748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11080/hello_world");
148748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
149748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
150748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
151748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_READDATA, &pos);
152748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
153748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      /*
154748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat         // by not giving the file size, we force chunking!
155748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat         curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
156748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat       */
157748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
158748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
159748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
160748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
161748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      // NOTE: use of CONNECTTIMEOUT without also
162748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      //   setting NOSIGNAL results in really weird
163748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      //   crashes on my system!
164748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
165748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_perform (c);
166748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_cleanup (c);
167748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
168748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fprintf (stderr, "\n");
169748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  zzuf_socat_stop ();
170748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_stop_daemon (d);
171748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
172748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
173748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
174748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
175748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel ErattestMultithreadedPut ()
176748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
177748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Daemon *d;
178748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURL *c;
179748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char buf[2048];
180748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC cbc;
181748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int pos = 0;
182748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int done_flag = 0;
183748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURLcode errornum;
184748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
185748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.buf = buf;
186748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.size = 2048;
187748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.pos = 0;
188748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
189748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        11081,
190748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
191748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (d == NULL)
192748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 16;
193748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  c = curl_easy_init ();
194748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
195748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
196748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
197748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
198748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
199748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
200748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /*
201748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     // by not giving the file size, we force chunking!
202748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
203748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   */
204748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
205748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
206748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
207748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
208748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  // NOTE: use of CONNECTTIMEOUT without also
209748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //   setting NOSIGNAL results in really weird
210748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //   crashes on my system!
211748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
212748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (CURLE_OK != (errornum = curl_easy_perform (c)))
213748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
214748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr,
215748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               "curl_easy_perform failed: `%s'\n",
216748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               curl_easy_strerror (errornum));
217748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_cleanup (c);
218748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      MHD_stop_daemon (d);
219748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return 32;
220748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
221748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_cleanup (c);
222748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_stop_daemon (d);
223748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (cbc.pos != strlen ("/hello_world"))
224748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 64;
225748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
226748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 128;
227748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
228748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
229748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
230748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
231748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
232748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
233748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel ErattestExternalPut ()
234748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
235748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Daemon *d;
236748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURL *c;
237748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char buf[2048];
238748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC cbc;
239748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURLM *multi;
240748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURLMcode mret;
241748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fd_set rs;
242748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fd_set ws;
243748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fd_set es;
244748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int max;
245748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int running;
246748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  time_t start;
247748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct timeval tv;
248748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int pos = 0;
249748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int done_flag = 0;
250748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int i;
251748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
252748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  multi = NULL;
253748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.buf = buf;
254748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.size = 2048;
255748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.pos = 0;
256748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  d = MHD_start_daemon (MHD_USE_DEBUG,
257748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        11082,
258748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
259748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (d == NULL)
260748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 256;
261748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
262748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  multi = curl_multi_init ();
263748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (multi == NULL)
264748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
265748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      MHD_stop_daemon (d);
266748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return 512;
267748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
268748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  zzuf_socat_start ();
269748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  for (i = 0; i < LOOP_COUNT; i++)
270748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
271748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr, ".");
272748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      c = curl_easy_init ();
273748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11082/hello_world");
274748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
275748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
276748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
277748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_READDATA, &pos);
278748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
279748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      /*
280748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat         // by not giving the file size, we force chunking!
281748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat         curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
282748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat       */
283748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
284748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
285748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
286748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
287748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      // NOTE: use of CONNECTTIMEOUT without also
288748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      //   setting NOSIGNAL results in really weird
289748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      //   crashes on my system!
290748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
291748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
292748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
293748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      mret = curl_multi_add_handle (multi, c);
294748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (mret != CURLM_OK)
295748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
296748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_multi_cleanup (multi);
297748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_cleanup (c);
298748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          zzuf_socat_stop ();
299748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          MHD_stop_daemon (d);
300748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          return 1024;
301748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
302748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      start = time (NULL);
303748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      while ((time (NULL) - start < 5) && (c != NULL))
304748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
305748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          max = 0;
306748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          FD_ZERO (&rs);
307748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          FD_ZERO (&ws);
308748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          FD_ZERO (&es);
309748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_multi_perform (multi, &running);
310748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
311748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (mret != CURLM_OK)
312748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            {
313748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_multi_remove_handle (multi, c);
314748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_multi_cleanup (multi);
315748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_easy_cleanup (c);
316748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              zzuf_socat_stop ();
317748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              MHD_stop_daemon (d);
318748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              return 2048;
319748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            }
320748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
321748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            {
322748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_multi_remove_handle (multi, c);
323748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_multi_cleanup (multi);
324748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_easy_cleanup (c);
325748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              zzuf_socat_stop ();
326748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              MHD_stop_daemon (d);
327748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              return 4096;
328748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            }
329748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          tv.tv_sec = 0;
330748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          tv.tv_usec = 1000;
331748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          select (max + 1, &rs, &ws, &es, &tv);
332748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_multi_perform (multi, &running);
333748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (running == 0)
334748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            {
335748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_multi_info_read (multi, &running);
336748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_multi_remove_handle (multi, c);
337748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              curl_easy_cleanup (c);
338748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              c = NULL;
339748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            }
340748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          MHD_run (d);
341748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
342748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (c != NULL)
343748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
344748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_multi_remove_handle (multi, c);
345748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          curl_easy_cleanup (c);
346748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
347748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
348748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fprintf (stderr, "\n");
349748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_multi_cleanup (multi);
350748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  zzuf_socat_stop ();
351748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_stop_daemon (d);
352748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
353748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
354748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
355748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
356748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
357748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint
358748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratmain (int argc, char *const *argv)
359748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
360748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int errorCount = 0;
361748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
362748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
363748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 2;
364748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  errorCount += testInternalPut ();
365748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  errorCount += testMultithreadedPut ();
366748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  errorCount += testExternalPut ();
367748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (errorCount != 0)
368748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    fprintf (stderr, "Error (code: %u)\n", errorCount);
369748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_global_cleanup ();
370748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return errorCount != 0;       /* 0 == pass */
371748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
372