aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2007-08-12 06:01:48 +0000
committerChristian Grothoff <christian@grothoff.org>2007-08-12 06:01:48 +0000
commit85b7d00955a8adb9e6d8d42ba37c5c0d53cafc53 (patch)
treea5c244da50ef0a5659e368cb9c1ac91b0861076c
parentc75bf1093162231d4e2f09f399f2d6039d2c321f (diff)
downloadlibmicrohttpd-85b7d00955a8adb9e6d8d42ba37c5c0d53cafc53.tar.gz
libmicrohttpd-85b7d00955a8adb9e6d8d42ba37c5c0d53cafc53.zip
formatting and versioning
-rw-r--r--README1
-rw-r--r--configure.ac4
-rw-r--r--doc/libmicrohttpd.36
-rw-r--r--src/daemon/Makefile.am4
-rw-r--r--src/daemon/connection.c1541
-rw-r--r--src/daemon/connection.h18
-rw-r--r--src/daemon/daemon.c747
-rw-r--r--src/daemon/daemontest.c153
-rw-r--r--src/daemon/daemontest_get.c470
-rw-r--r--src/daemon/daemontest_long_header.c321
-rw-r--r--src/daemon/daemontest_post.c538
-rw-r--r--src/daemon/daemontest_put.c562
-rw-r--r--src/daemon/fileserver_example.c113
-rw-r--r--src/daemon/internal.c15
-rw-r--r--src/daemon/internal.h67
-rw-r--r--src/daemon/memorypool.c147
-rw-r--r--src/daemon/memorypool.h16
-rw-r--r--src/daemon/minimal_example.c67
-rw-r--r--src/daemon/plibc.h774
-rw-r--r--src/daemon/response.c257
-rw-r--r--src/daemon/response.h2
-rw-r--r--src/include/microhttpd.h156
22 files changed, 2805 insertions, 3174 deletions
diff --git a/README b/README
index c88cec5c..48aeeeca 100644
--- a/README
+++ b/README
@@ -38,4 +38,3 @@ Documentation:
38============== 38==============
39- manual (texinfo, man) 39- manual (texinfo, man)
40- tutorial 40- tutorial
41- web page
diff --git a/configure.ac b/configure.ac
index de88f861..b87f8d95 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,8 +21,8 @@
21# 21#
22# 22#
23AC_PREREQ(2.57) 23AC_PREREQ(2.57)
24AC_INIT([libmicrohttpd], [0.0.0],[libmicrohttpd@gnunet.org]) 24AC_INIT([libmicrohttpd], [0.0.1],[libmicrohttpd@gnunet.org])
25AM_INIT_AUTOMAKE([libmicrohttpd], [0.0.0]) 25AM_INIT_AUTOMAKE([libmicrohttpd], [0.0.1])
26AM_CONFIG_HEADER([config.h]) 26AM_CONFIG_HEADER([config.h])
27 27
28AH_TOP([#define _GNU_SOURCE 1]) 28AH_TOP([#define _GNU_SOURCE 1])
diff --git a/doc/libmicrohttpd.3 b/doc/libmicrohttpd.3
index 4480c93c..3c478c72 100644
--- a/doc/libmicrohttpd.3
+++ b/doc/libmicrohttpd.3
@@ -5,11 +5,11 @@ libmicrohttpd \- library for embedding HTTP servers
5 5
6\fB#include <microhttpd.h> 6\fB#include <microhttpd.h>
7 7
8\fPInsert API here.
9
10.SH "DESCRIPTION" 8.SH "DESCRIPTION"
11.P 9.P
12Insert API description here. 10libmicrohttpd (short MHD) allows applications to easily integrate the functionality of a simple HTTP server.
11.P
12The details of the API are described in comments in the header file and on the webpage.
13 13
14.P 14.P
15.SH "SEE ALSO" 15.SH "SEE ALSO"
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index 80a8d751..0f11b662 100644
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
@@ -6,7 +6,7 @@ lib_LTLIBRARIES = \
6 libmicrohttpd.la 6 libmicrohttpd.la
7 7
8libmicrohttpd_la_LDFLAGS = \ 8libmicrohttpd_la_LDFLAGS = \
9 -export-dynamic -version-info 0:0:0 9 -export-dynamic -version-info 0:1:0
10libmicrohttpd_la_SOURCES = \ 10libmicrohttpd_la_SOURCES = \
11 connection.c connection.h \ 11 connection.c connection.h \
12 daemon.c \ 12 daemon.c \
@@ -92,4 +92,4 @@ daemontest_long_header_LDADD = \
92 $(top_builddir)/src/daemon/libmicrohttpd.la \ 92 $(top_builddir)/src/daemon/libmicrohttpd.la \
93 @LIBCURL@ 93 @LIBCURL@
94 94
95endif \ No newline at end of file 95endif
diff --git a/src/daemon/connection.c b/src/daemon/connection.c
index b5d0b3dd..fdbc975c 100644
--- a/src/daemon/connection.c
+++ b/src/daemon/connection.c
@@ -50,29 +50,29 @@
50 * @return number of entries iterated over 50 * @return number of entries iterated over
51 */ 51 */
52int 52int
53MHD_get_connection_values(struct MHD_Connection * connection, 53MHD_get_connection_values (struct MHD_Connection *connection,
54 enum MHD_ValueKind kind, 54 enum MHD_ValueKind kind,
55 MHD_KeyValueIterator iterator, 55 MHD_KeyValueIterator iterator, void *iterator_cls)
56 void * iterator_cls) { 56{
57 int ret; 57 int ret;
58 struct MHD_HTTP_Header * pos; 58 struct MHD_HTTP_Header *pos;
59 59
60 if (connection == NULL) 60 if (connection == NULL)
61 return -1; 61 return -1;
62 ret = 0; 62 ret = 0;
63 pos = connection->headers_received; 63 pos = connection->headers_received;
64 while (pos != NULL) { 64 while (pos != NULL)
65 if (0 != (pos->kind & kind)) { 65 {
66 ret++; 66 if (0 != (pos->kind & kind))
67 if ( (iterator != NULL) && 67 {
68 (MHD_YES != iterator(iterator_cls, 68 ret++;
69 kind, 69 if ((iterator != NULL) &&
70 pos->header, 70 (MHD_YES != iterator (iterator_cls,
71 pos->value)) ) 71 kind, pos->header, pos->value)))
72 return ret; 72 return ret;
73 }
74 pos = pos->next;
73 } 75 }
74 pos = pos->next;
75 }
76 return ret; 76 return ret;
77} 77}
78 78
@@ -85,21 +85,20 @@ MHD_get_connection_values(struct MHD_Connection * connection,
85 * @return NULL if no such item was found 85 * @return NULL if no such item was found
86 */ 86 */
87const char * 87const char *
88MHD_lookup_connection_value(struct MHD_Connection * connection, 88MHD_lookup_connection_value (struct MHD_Connection *connection,
89 enum MHD_ValueKind kind, 89 enum MHD_ValueKind kind, const char *key)
90 const char * key) { 90{
91 struct MHD_HTTP_Header * pos; 91 struct MHD_HTTP_Header *pos;
92 92
93 if (connection == NULL) 93 if (connection == NULL)
94 return NULL; 94 return NULL;
95 pos = connection->headers_received; 95 pos = connection->headers_received;
96 while (pos != NULL) { 96 while (pos != NULL)
97 if ( (0 != (pos->kind & kind)) && 97 {
98 (0 == strcasecmp(key, 98 if ((0 != (pos->kind & kind)) && (0 == strcasecmp (key, pos->header)))
99 pos->header)) ) 99 return pos->value;
100 return pos->value; 100 pos = pos->next;
101 pos = pos->next; 101 }
102 }
103 return NULL; 102 return NULL;
104} 103}
105 104
@@ -114,25 +113,24 @@ MHD_lookup_connection_value(struct MHD_Connection * connection,
114 * MHD_YES on success or if message has been queued 113 * MHD_YES on success or if message has been queued
115 */ 114 */
116int 115int
117MHD_queue_response(struct MHD_Connection * connection, 116MHD_queue_response (struct MHD_Connection *connection,
118 unsigned int status_code, 117 unsigned int status_code, struct MHD_Response *response)
119 struct MHD_Response * response) { 118{
120 if ( (connection == NULL) || 119 if ((connection == NULL) ||
121 (response == NULL) || 120 (response == NULL) ||
122 (connection->response != NULL) || 121 (connection->response != NULL) ||
123 (connection->bodyReceived == 0) || 122 (connection->bodyReceived == 0) || (connection->headersReceived == 0))
124 (connection->headersReceived == 0) ) 123 return MHD_NO;
125 return MHD_NO; 124 MHD_increment_response_rc (response);
126 MHD_increment_response_rc(response);
127 connection->response = response; 125 connection->response = response;
128 connection->responseCode = status_code; 126 connection->responseCode = status_code;
129 if ( (connection->method != NULL) && 127 if ((connection->method != NULL) &&
130 (0 == strcasecmp(connection->method, 128 (0 == strcasecmp (connection->method, MHD_HTTP_METHOD_HEAD)))
131 MHD_HTTP_METHOD_HEAD)) ) { 129 {
132 /* if this is a "HEAD" request, pretend that we 130 /* if this is a "HEAD" request, pretend that we
133 have already sent the full message body */ 131 have already sent the full message body */
134 connection->messagePos = response->total_size; 132 connection->messagePos = response->total_size;
135 } 133 }
136 return MHD_YES; 134 return MHD_YES;
137} 135}
138 136
@@ -140,20 +138,20 @@ MHD_queue_response(struct MHD_Connection * connection,
140 * Do we (still) need to send a 100 continue 138 * Do we (still) need to send a 100 continue
141 * message for this connection? 139 * message for this connection?
142 */ 140 */
143static int 141static int
144MHD_need_100_continue(struct MHD_Connection * connection) { 142MHD_need_100_continue (struct MHD_Connection *connection)
145 const char * expect; 143{
144 const char *expect;
146 145
147 return ( (connection->version != NULL) && 146 return ((connection->version != NULL) &&
148 (0 == strcasecmp(connection->version, 147 (0 == strcasecmp (connection->version,
149 MHD_HTTP_VERSION_1_1)) && 148 MHD_HTTP_VERSION_1_1)) &&
150 (connection->headersReceived == 1) && 149 (connection->headersReceived == 1) &&
151 (NULL != (expect = MHD_lookup_connection_value(connection, 150 (NULL != (expect = MHD_lookup_connection_value (connection,
152 MHD_HEADER_KIND, 151 MHD_HEADER_KIND,
153 MHD_HTTP_HEADER_EXPECT))) && 152 MHD_HTTP_HEADER_EXPECT)))
154 (0 == strcasecmp(expect, 153 && (0 == strcasecmp (expect, "100-continue"))
155 "100-continue")) && 154 && (connection->continuePos < strlen (HTTP_100_CONTINUE)));
156 (connection->continuePos < strlen(HTTP_100_CONTINUE)) );
157} 155}
158 156
159/** 157/**
@@ -162,49 +160,56 @@ MHD_need_100_continue(struct MHD_Connection * connection) {
162 * @return MHD_YES on success 160 * @return MHD_YES on success
163 */ 161 */
164int 162int
165MHD_connection_get_fdset(struct MHD_Connection * connection, 163MHD_connection_get_fdset (struct MHD_Connection *connection,
166 fd_set * read_fd_set, 164 fd_set * read_fd_set,
167 fd_set * write_fd_set, 165 fd_set * write_fd_set,
168 fd_set * except_fd_set, 166 fd_set * except_fd_set, int *max_fd)
169 int * max_fd) { 167{
170 int fd; 168 int fd;
171 void * buf; 169 void *buf;
172 170
173 fd = connection->socket_fd; 171 fd = connection->socket_fd;
174 if (fd == -1) 172 if (fd == -1)
175 return MHD_YES; 173 return MHD_YES;
176 if ( (connection->read_close == MHD_NO) && 174 if ((connection->read_close == MHD_NO) &&
177 ( (connection->headersReceived == 0) || 175 ((connection->headersReceived == 0) ||
178 (connection->readLoc < connection->read_buffer_size) ) ) { 176 (connection->readLoc < connection->read_buffer_size)))
179 FD_SET(fd, read_fd_set); 177 {
180 if (fd > *max_fd) 178 FD_SET (fd, read_fd_set);
181 *max_fd = fd; 179 if (fd > *max_fd)
182 } else { 180 *max_fd = fd;
183 if ( (connection->read_close == MHD_NO) && 181 }
184 ( (connection->headersReceived == 1) && 182 else
185 (connection->post_processed == MHD_NO) && 183 {
186 (connection->readLoc == connection->read_buffer_size) ) ) { 184 if ((connection->read_close == MHD_NO) &&
187 /* try growing the read buffer, just in case */ 185 ((connection->headersReceived == 1) &&
188 buf = MHD_pool_reallocate(connection->pool, 186 (connection->post_processed == MHD_NO) &&
189 connection->read_buffer, 187 (connection->readLoc == connection->read_buffer_size)))
190 connection->read_buffer_size, 188 {
191 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE); 189 /* try growing the read buffer, just in case */
192 if (buf != NULL) { 190 buf = MHD_pool_reallocate (connection->pool,
193 /* we can actually grow the buffer, do it! */ 191 connection->read_buffer,
194 connection->read_buffer = buf; 192 connection->read_buffer_size,
195 connection->read_buffer_size = connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; 193 connection->read_buffer_size * 2 +
196 FD_SET(fd, read_fd_set); 194 MHD_BUF_INC_SIZE);
197 if (fd > *max_fd) 195 if (buf != NULL)
198 *max_fd = fd; 196 {
199 } 197 /* we can actually grow the buffer, do it! */
198 connection->read_buffer = buf;
199 connection->read_buffer_size =
200 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
201 FD_SET (fd, read_fd_set);
202 if (fd > *max_fd)
203 *max_fd = fd;
204 }
205 }
206 }
207 if ((connection->response != NULL) || MHD_need_100_continue (connection))
208 {
209 FD_SET (fd, write_fd_set);
210 if (fd > *max_fd)
211 *max_fd = fd;
200 } 212 }
201 }
202 if ( (connection->response != NULL) ||
203 MHD_need_100_continue(connection) ) {
204 FD_SET(fd, write_fd_set);
205 if (fd > *max_fd)
206 *max_fd = fd;
207 }
208 return MHD_YES; 213 return MHD_YES;
209} 214}
210 215
@@ -216,9 +221,10 @@ MHD_connection_get_fdset(struct MHD_Connection * connection,
216 * @param status_code the response code to send (413 or 414) 221 * @param status_code the response code to send (413 or 414)
217 */ 222 */
218static void 223static void
219MHD_excessive_data_handler(struct MHD_Connection * connection, 224MHD_excessive_data_handler (struct MHD_Connection *connection,
220 unsigned int status_code) { 225 unsigned int status_code)
221 struct MHD_Response * response; 226{
227 struct MHD_Response *response;
222 228
223 /* die, header far too long to be reasonable; 229 /* die, header far too long to be reasonable;
224 FIXME: send proper response to client 230 FIXME: send proper response to client
@@ -226,16 +232,12 @@ MHD_excessive_data_handler(struct MHD_Connection * connection,
226 connection->read_close = MHD_YES; 232 connection->read_close = MHD_YES;
227 connection->headersReceived = MHD_YES; 233 connection->headersReceived = MHD_YES;
228 connection->bodyReceived = MHD_YES; 234 connection->bodyReceived = MHD_YES;
229 MHD_DLOG(connection->daemon, 235 MHD_DLOG (connection->daemon,
230 "Received excessively long header, closing connection.\n"); 236 "Received excessively long header, closing connection.\n");
231 response = MHD_create_response_from_data(strlen(REQUEST_TOO_BIG), 237 response = MHD_create_response_from_data (strlen (REQUEST_TOO_BIG),
232 REQUEST_TOO_BIG, 238 REQUEST_TOO_BIG, MHD_NO, MHD_NO);
233 MHD_NO, 239 MHD_queue_response (connection, status_code, response);
234 MHD_NO); 240 MHD_destroy_response (response);
235 MHD_queue_response(connection,
236 status_code,
237 response);
238 MHD_destroy_response(response);
239} 241}
240 242
241/** 243/**
@@ -247,41 +249,47 @@ MHD_excessive_data_handler(struct MHD_Connection * connection,
247 * return NULL. Otherwise return a pointer to the line. 249 * return NULL. Otherwise return a pointer to the line.
248 */ 250 */
249static char * 251static char *
250MHD_get_next_header_line(struct MHD_Connection * connection) { 252MHD_get_next_header_line (struct MHD_Connection *connection)
251 char * rbuf; 253{
254 char *rbuf;
252 size_t pos; 255 size_t pos;
253 256
254 if (connection->readLoc == 0) 257 if (connection->readLoc == 0)
255 return NULL; 258 return NULL;
256 pos = 0; 259 pos = 0;
257 rbuf = connection->read_buffer; 260 rbuf = connection->read_buffer;
258 while ( (pos < connection->readLoc - 1) && 261 while ((pos < connection->readLoc - 1) &&
259 (rbuf[pos] != '\r') && 262 (rbuf[pos] != '\r') && (rbuf[pos] != '\n'))
260 (rbuf[pos] != '\n') )
261 pos++; 263 pos++;
262 if (pos == connection->readLoc - 1) { 264 if (pos == connection->readLoc - 1)
263 /* not found, consider growing... */ 265 {
264 if (connection->readLoc == connection->read_buffer_size) { 266 /* not found, consider growing... */
265 rbuf = MHD_pool_reallocate(connection->pool, 267 if (connection->readLoc == connection->read_buffer_size)
266 connection->read_buffer, 268 {
267 connection->read_buffer_size, 269 rbuf = MHD_pool_reallocate (connection->pool,
268 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE); 270 connection->read_buffer,
269 if (rbuf == NULL) { 271 connection->read_buffer_size,
270 MHD_excessive_data_handler(connection, 272 connection->read_buffer_size * 2 +
271 (connection->url != NULL) 273 MHD_BUF_INC_SIZE);
272 ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE 274 if (rbuf == NULL)
273 : MHD_HTTP_REQUEST_URI_TOO_LONG); 275 {
274 } else { 276 MHD_excessive_data_handler (connection,
275 connection->read_buffer_size = connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; 277 (connection->url != NULL)
276 connection->read_buffer = rbuf; 278 ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
277 } 279 : MHD_HTTP_REQUEST_URI_TOO_LONG);
280 }
281 else
282 {
283 connection->read_buffer_size =
284 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
285 connection->read_buffer = rbuf;
286 }
287 }
288 return NULL;
278 } 289 }
279 return NULL;
280 }
281 /* found, check if we have proper CRLF */ 290 /* found, check if we have proper CRLF */
282 if ( (rbuf[pos] == '\r') && 291 if ((rbuf[pos] == '\r') && (rbuf[pos + 1] == '\n'))
283 (rbuf[pos+1] == '\n') ) 292 rbuf[pos++] = '\0'; /* skip both r and n */
284 rbuf[pos++] = '\0'; /* skip both r and n */
285 rbuf[pos++] = '\0'; 293 rbuf[pos++] = '\0';
286 connection->read_buffer += pos; 294 connection->read_buffer += pos;
287 connection->read_buffer_size -= pos; 295 connection->read_buffer_size -= pos;
@@ -293,22 +301,21 @@ MHD_get_next_header_line(struct MHD_Connection * connection) {
293 * @return MHD_NO on failure (out of memory), MHD_YES for success 301 * @return MHD_NO on failure (out of memory), MHD_YES for success
294 */ 302 */
295static int 303static int
296MHD_connection_add_header(struct MHD_Connection * connection, 304MHD_connection_add_header (struct MHD_Connection *connection,
297 char * key, 305 char *key, char *value, enum MHD_ValueKind kind)
298 char * value, 306{
299 enum MHD_ValueKind kind) { 307 struct MHD_HTTP_Header *hdr;
300 struct MHD_HTTP_Header * hdr;
301 308
302 hdr = MHD_pool_allocate(connection->pool, 309 hdr = MHD_pool_allocate (connection->pool,
303 sizeof(struct MHD_HTTP_Header), 310 sizeof (struct MHD_HTTP_Header), MHD_YES);
304 MHD_YES); 311 if (hdr == NULL)
305 if (hdr == NULL) { 312 {
306 MHD_DLOG(connection->daemon, 313 MHD_DLOG (connection->daemon,
307 "Not enough memory to allocate header record!\n"); 314 "Not enough memory to allocate header record!\n");
308 MHD_excessive_data_handler(connection, 315 MHD_excessive_data_handler (connection,
309 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); 316 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
310 return MHD_NO; 317 return MHD_NO;
311 } 318 }
312 hdr->next = connection->headers_received; 319 hdr->next = connection->headers_received;
313 hdr->header = key; 320 hdr->header = key;
314 hdr->value = value; 321 hdr->value = value;
@@ -319,60 +326,57 @@ MHD_connection_add_header(struct MHD_Connection * connection,
319 326
320/** 327/**
321 * Process escape sequences ('+'=space, %HH) 328 * Process escape sequences ('+'=space, %HH)
322 */ 329 */
323static void 330static void
324MHD_http_unescape(char * val) { 331MHD_http_unescape (char *val)
325 char * esc; 332{
333 char *esc;
326 unsigned int num; 334 unsigned int num;
327 335
328 while (NULL != (esc = strstr(val, "+"))) 336 while (NULL != (esc = strstr (val, "+")))
329 *esc = ' '; 337 *esc = ' ';
330 while (NULL != (esc = strstr(val, "%"))) { 338 while (NULL != (esc = strstr (val, "%")))
331 if ( (1 == sscanf(&esc[1], 339 {
332 "%2x", 340 if ((1 == sscanf (&esc[1],
333 &num)) || 341 "%2x", &num)) || (1 == sscanf (&esc[1], "%2X", &num)))
334 (1 == sscanf(&esc[1], 342 {
335 "%2X", 343 esc[0] = (unsigned char) num;
336 &num)) ) { 344 memmove (&esc[1], &esc[3], strlen (&esc[3]));
337 esc[0] = (unsigned char) num; 345 }
338 memmove(&esc[1], 346 val = esc + 1;
339 &esc[3],
340 strlen(&esc[3]));
341 } 347 }
342 val = esc+1;
343 }
344} 348}
345 349
346/** 350/**
347 * @return MHD_NO on failure (out of memory), MHD_YES for success 351 * @return MHD_NO on failure (out of memory), MHD_YES for success
348 */ 352 */
349static int 353static int
350parse_arguments(enum MHD_ValueKind kind, 354parse_arguments (enum MHD_ValueKind kind,
351 struct MHD_Connection * connection, 355 struct MHD_Connection *connection, char *args)
352 char * args) { 356{
353 char * equals; 357 char *equals;
354 char * amper; 358 char *amper;
355 359
356 while (args != NULL) { 360 while (args != NULL)
357 equals = strstr(args, "="); 361 {
358 if (equals == NULL) 362 equals = strstr (args, "=");
359 return MHD_NO; /* invalid, ignore */ 363 if (equals == NULL)
360 equals[0] = '\0'; 364 return MHD_NO; /* invalid, ignore */
361 equals++; 365 equals[0] = '\0';
362 amper = strstr(equals, "&"); 366 equals++;
363 if (amper != NULL) { 367 amper = strstr (equals, "&");
364 amper[0] = '\0'; 368 if (amper != NULL)
365 amper++; 369 {
370 amper[0] = '\0';
371 amper++;
372 }
373 MHD_http_unescape (args);
374 MHD_http_unescape (equals);
375 if (MHD_NO == MHD_connection_add_header (connection,
376 args, equals, kind))
377 return MHD_NO;
378 args = amper;
366 } 379 }
367 MHD_http_unescape(args);
368 MHD_http_unescape(equals);
369 if (MHD_NO == MHD_connection_add_header(connection,
370 args,
371 equals,
372 kind))
373 return MHD_NO;
374 args = amper;
375 }
376 return MHD_YES; 380 return MHD_YES;
377} 381}
378 382
@@ -382,68 +386,63 @@ parse_arguments(enum MHD_ValueKind kind,
382 * @return MHD_YES for success, MHD_NO for failure (malformed, out of memory) 386 * @return MHD_YES for success, MHD_NO for failure (malformed, out of memory)
383 */ 387 */
384static int 388static int
385MHD_parse_cookie_header(struct MHD_Connection * connection) { 389MHD_parse_cookie_header (struct MHD_Connection *connection)
386 const char * hdr; 390{
387 char * cpy; 391 const char *hdr;
388 char * pos; 392 char *cpy;
389 char * semicolon; 393 char *pos;
390 char * equals; 394 char *semicolon;
395 char *equals;
391 int quotes; 396 int quotes;
392 397
393 hdr = MHD_lookup_connection_value(connection, 398 hdr = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "Cookie");
394 MHD_HEADER_KIND,
395 "Cookie");
396 if (hdr == NULL) 399 if (hdr == NULL)
397 return MHD_YES; 400 return MHD_YES;
398 cpy = MHD_pool_allocate(connection->pool, 401 cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES);
399 strlen(hdr)+1, 402 if (cpy == NULL)
400 MHD_YES); 403 {
401 if (cpy == NULL) { 404 MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n");
402 MHD_DLOG(connection->daemon, 405 MHD_excessive_data_handler (connection,
403 "Not enough memory to parse cookies!\n"); 406 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
404 MHD_excessive_data_handler(connection, 407 return MHD_NO;
405 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
406 return MHD_NO;
407 }
408 memcpy(cpy,
409 hdr,
410 strlen(hdr)+1);
411 pos = cpy;
412 while (pos != NULL) {
413 equals = strstr(pos, "=");
414 if (equals == NULL)
415 break;
416 equals[0] = '\0';
417 equals++;
418 quotes = 0;
419 semicolon = equals;
420 while ( (semicolon[0] != '\0') &&
421 ( (quotes != 0) ||
422 ( (semicolon[0] != ';') &&
423 (semicolon[0] != ',') ) ) ) {
424 if (semicolon[0] == '"')
425 quotes = (quotes + 1) & 1;
426 semicolon++;
427 }
428 if (semicolon[0] == '\0')
429 semicolon = NULL;
430 if (semicolon != NULL) {
431 semicolon[0] = '\0';
432 semicolon++;
433 } 408 }
434 /* remove quotes */ 409 memcpy (cpy, hdr, strlen (hdr) + 1);
435 if ( (equals[0] == '"') && 410 pos = cpy;
436 (equals[strlen(equals)-1] == '"') ) { 411 while (pos != NULL)
437 equals[strlen(equals)-1] = '\0'; 412 {
413 equals = strstr (pos, "=");
414 if (equals == NULL)
415 break;
416 equals[0] = '\0';
438 equals++; 417 equals++;
418 quotes = 0;
419 semicolon = equals;
420 while ((semicolon[0] != '\0') &&
421 ((quotes != 0) ||
422 ((semicolon[0] != ';') && (semicolon[0] != ','))))
423 {
424 if (semicolon[0] == '"')
425 quotes = (quotes + 1) & 1;
426 semicolon++;
427 }
428 if (semicolon[0] == '\0')
429 semicolon = NULL;
430 if (semicolon != NULL)
431 {
432 semicolon[0] = '\0';
433 semicolon++;
434 }
435 /* remove quotes */
436 if ((equals[0] == '"') && (equals[strlen (equals) - 1] == '"'))
437 {
438 equals[strlen (equals) - 1] = '\0';
439 equals++;
440 }
441 if (MHD_NO == MHD_connection_add_header (connection,
442 pos, equals, MHD_COOKIE_KIND))
443 return MHD_NO;
444 pos = semicolon;
439 } 445 }
440 if (MHD_NO == MHD_connection_add_header(connection,
441 pos,
442 equals,
443 MHD_COOKIE_KIND))
444 return MHD_NO;
445 pos = semicolon;
446 }
447 return MHD_YES; 446 return MHD_YES;
448} 447}
449 448
@@ -455,33 +454,33 @@ MHD_parse_cookie_header(struct MHD_Connection * connection) {
455 * @return MHD_YES if the line is ok, MHD_NO if it is malformed 454 * @return MHD_YES if the line is ok, MHD_NO if it is malformed
456 */ 455 */
457static int 456static int
458parse_initial_message_line(struct MHD_Connection * connection, 457parse_initial_message_line (struct MHD_Connection *connection, char *line)
459 char * line) { 458{
460 char * uri; 459 char *uri;
461 char * httpVersion; 460 char *httpVersion;
462 char * args; 461 char *args;
463 462
464 uri = strstr(line, " "); 463 uri = strstr (line, " ");
465 if (uri == NULL) 464 if (uri == NULL)
466 return MHD_NO; /* serious error */ 465 return MHD_NO; /* serious error */
467 uri[0] = '\0'; 466 uri[0] = '\0';
468 connection->method = line; 467 connection->method = line;
469 uri++; 468 uri++;
470 while (uri[0] == ' ') 469 while (uri[0] == ' ')
471 uri++; 470 uri++;
472 httpVersion = strstr(uri, " "); 471 httpVersion = strstr (uri, " ");
473 if (httpVersion != NULL) { 472 if (httpVersion != NULL)
474 httpVersion[0] = '\0'; 473 {
475 httpVersion++; 474 httpVersion[0] = '\0';
476 } 475 httpVersion++;
477 args = strstr(uri, "?"); 476 }
478 if (args != NULL) { 477 args = strstr (uri, "?");
479 args[0] = '\0'; 478 if (args != NULL)
480 args++; 479 {
481 parse_arguments(MHD_GET_ARGUMENT_KIND, 480 args[0] = '\0';
482 connection, 481 args++;
483 args); 482 parse_arguments (MHD_GET_ARGUMENT_KIND, connection, args);
484 } 483 }
485 connection->url = uri; 484 connection->url = uri;
486 if (httpVersion == NULL) 485 if (httpVersion == NULL)
487 connection->version = ""; 486 connection->version = "";
@@ -502,131 +501,137 @@ parse_initial_message_line(struct MHD_Connection * connection,
502 * size of the body is unknown, it should be set to -1. 501 * size of the body is unknown, it should be set to -1.
503 */ 502 */
504static void 503static void
505MHD_parse_connection_headers(struct MHD_Connection * connection) { 504MHD_parse_connection_headers (struct MHD_Connection *connection)
506 char * last; 505{
507 char * line; 506 char *last;
508 char * colon; 507 char *line;
509 char * tmp; 508 char *colon;
510 const char * clen; 509 char *tmp;
511 const char * end; 510 const char *clen;
511 const char *end;
512 unsigned long long cval; 512 unsigned long long cval;
513 513
514 if (connection->bodyReceived == 1) 514 if (connection->bodyReceived == 1)
515 abort(); 515 abort ();
516 last = NULL; 516 last = NULL;
517 while (NULL != (line = MHD_get_next_header_line(connection))) { 517 while (NULL != (line = MHD_get_next_header_line (connection)))
518 if (last != NULL) { 518 {
519 if ( (line[0] == ' ') || 519 if (last != NULL)
520 (line[0] == '\t') ) { 520 {
521 /* value was continued on the next line, see 521 if ((line[0] == ' ') || (line[0] == '\t'))
522 http://www.jmarshall.com/easy/http/ */ 522 {
523 last = MHD_pool_reallocate(connection->pool, 523 /* value was continued on the next line, see
524 last, 524 http://www.jmarshall.com/easy/http/ */
525 strlen(last)+1, 525 last = MHD_pool_reallocate (connection->pool,
526 strlen(line) + strlen(last) + 1); 526 last,
527 if (last == NULL) { 527 strlen (last) + 1,
528 MHD_excessive_data_handler(connection, 528 strlen (line) + strlen (last) + 1);
529 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); 529 if (last == NULL)
530 break; 530 {
531 } 531 MHD_excessive_data_handler (connection,
532 tmp = line; 532 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
533 while ( (tmp[0] == ' ') || 533 break;
534 (tmp[0] == '\t') ) 534 }
535 tmp++; /* skip whitespace at start of 2nd line */ 535 tmp = line;
536 strcat(last, tmp); 536 while ((tmp[0] == ' ') || (tmp[0] == '\t'))
537 continue; /* possibly more than 2 lines... */ 537 tmp++; /* skip whitespace at start of 2nd line */
538 } else { 538 strcat (last, tmp);
539 if (MHD_NO == MHD_connection_add_header(connection, 539 continue; /* possibly more than 2 lines... */
540 last, 540 }
541 colon, 541 else
542 MHD_HEADER_KIND)) 542 {
543 return; 543 if (MHD_NO == MHD_connection_add_header (connection,
544 last = NULL; 544 last,
545 } 545 colon,
546 MHD_HEADER_KIND))
547 return;
548 last = NULL;
549 }
550 }
551 if (connection->url == NULL)
552 {
553 /* line must be request line (first line of header) */
554 if (MHD_NO == parse_initial_message_line (connection, line))
555 goto DIE;
556 continue;
557 }
558 /* check if this is the end of the header */
559 if (strlen (line) == 0)
560 {
561 /* end of header */
562 connection->headersReceived = 1;
563 clen = MHD_lookup_connection_value (connection,
564 MHD_HEADER_KIND,
565 MHD_HTTP_HEADER_CONTENT_LENGTH);
566 if (clen != NULL)
567 {
568 if (1 != sscanf (clen, "%llu", &cval))
569 {
570 MHD_DLOG (connection->daemon,
571 "Failed to parse `%s' header `%s', closing connection.\n",
572 MHD_HTTP_HEADER_CONTENT_LENGTH, clen);
573 goto DIE;
574 }
575 connection->uploadSize = cval;
576 connection->bodyReceived = cval == 0 ? 1 : 0;
577 }
578 else
579 {
580 if (NULL == MHD_lookup_connection_value (connection,
581 MHD_HEADER_KIND,
582 MHD_HTTP_HEADER_TRANSFER_ENCODING))
583 {
584 /* this request does not have a body */
585 connection->uploadSize = 0;
586 connection->bodyReceived = 1;
587 }
588 else
589 {
590 connection->uploadSize = -1; /* unknown size */
591 connection->bodyReceived = 0;
592 }
593 }
594 end = MHD_lookup_connection_value (connection,
595 MHD_HEADER_KIND,
596 MHD_HTTP_HEADER_CONNECTION);
597 if ((end != NULL) && (0 == strcasecmp (end, "close")))
598 {
599 /* other side explicitly requested
600 that we close the connection after
601 this request */
602 connection->read_close = MHD_YES;
603 }
604 break;
605 }
606 /* line should be normal header line, find colon */
607 colon = strstr (line, ":");
608 if (colon == NULL)
609 {
610 /* error in header line, die hard */
611 MHD_DLOG (connection->daemon,
612 "Received malformed line (no colon), closing connection.\n");
613 goto DIE;
614 }
615 /* zero-terminate header */
616 colon[0] = '\0';
617 colon++; /* advance to value */
618 while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t')))
619 colon++;
620 /* we do the actual adding of the connection
621 header at the beginning of the while
622 loop since we need to be able to inspect
623 the *next* header line (in case it starts
624 with a space...) */
625 last = line;
546 } 626 }
547 if (connection->url == NULL) { 627 if ((last != NULL) &&
548 /* line must be request line (first line of header) */ 628 (MHD_NO == MHD_connection_add_header (connection,
549 if (MHD_NO == parse_initial_message_line(connection, 629 last, colon, MHD_HEADER_KIND)))
550 line)) 630 return; /* error */
551 goto DIE; 631 MHD_parse_cookie_header (connection);
552 continue;
553 }
554 /* check if this is the end of the header */
555 if (strlen(line) == 0) {
556 /* end of header */
557 connection->headersReceived = 1;
558 clen = MHD_lookup_connection_value(connection,
559 MHD_HEADER_KIND,
560 MHD_HTTP_HEADER_CONTENT_LENGTH);
561 if (clen != NULL) {
562 if (1 != sscanf(clen,
563 "%llu",
564 &cval)) {
565 MHD_DLOG(connection->daemon,
566 "Failed to parse `%s' header `%s', closing connection.\n",
567 MHD_HTTP_HEADER_CONTENT_LENGTH,
568 clen);
569 goto DIE;
570 }
571 connection->uploadSize = cval;
572 connection->bodyReceived = cval == 0 ? 1 : 0;
573 } else {
574 if (NULL == MHD_lookup_connection_value(connection,
575 MHD_HEADER_KIND,
576 MHD_HTTP_HEADER_TRANSFER_ENCODING)) {
577 /* this request does not have a body */
578 connection->uploadSize = 0;
579 connection->bodyReceived = 1;
580 } else {
581 connection->uploadSize = -1; /* unknown size */
582 connection->bodyReceived = 0;
583 }
584 }
585 end = MHD_lookup_connection_value(connection,
586 MHD_HEADER_KIND,
587 MHD_HTTP_HEADER_CONNECTION);
588 if ( (end != NULL) &&
589 (0 == strcasecmp(end,
590 "close")) ) {
591 /* other side explicitly requested
592 that we close the connection after
593 this request */
594 connection->read_close = MHD_YES;
595 }
596 break;
597 }
598 /* line should be normal header line, find colon */
599 colon = strstr(line, ":");
600 if (colon == NULL) {
601 /* error in header line, die hard */
602 MHD_DLOG(connection->daemon,
603 "Received malformed line (no colon), closing connection.\n");
604 goto DIE;
605 }
606 /* zero-terminate header */
607 colon[0] = '\0';
608 colon++; /* advance to value */
609 while ( (colon[0] != '\0') &&
610 ( (colon[0] == ' ') ||
611 (colon[0] == '\t') ) )
612 colon++;
613 /* we do the actual adding of the connection
614 header at the beginning of the while
615 loop since we need to be able to inspect
616 the *next* header line (in case it starts
617 with a space...) */
618 last = line;
619 }
620 if ( (last != NULL) &&
621 (MHD_NO == MHD_connection_add_header(connection,
622 last,
623 colon,
624 MHD_HEADER_KIND)) )
625 return; /* error */
626 MHD_parse_cookie_header(connection);
627 return; 632 return;
628 DIE: 633DIE:
629 CLOSE(connection->socket_fd); 634 CLOSE (connection->socket_fd);
630 connection->socket_fd = -1; 635 connection->socket_fd = -1;
631} 636}
632 637
@@ -635,16 +640,17 @@ MHD_parse_connection_headers(struct MHD_Connection * connection) {
635 * Find the handler responsible for this request. 640 * Find the handler responsible for this request.
636 */ 641 */
637static struct MHD_Access_Handler * 642static struct MHD_Access_Handler *
638MHD_find_access_handler(struct MHD_Connection * connection) { 643MHD_find_access_handler (struct MHD_Connection *connection)
639 struct MHD_Access_Handler * pos; 644{
645 struct MHD_Access_Handler *pos;
640 646
641 pos = connection->daemon->handlers; 647 pos = connection->daemon->handlers;
642 while (pos != NULL) { 648 while (pos != NULL)
643 if (0 == strcmp(connection->url, 649 {
644 pos->uri_prefix)) 650 if (0 == strcmp (connection->url, pos->uri_prefix))
645 return pos; 651 return pos;
646 pos = pos->next; 652 pos = pos->next;
647 } 653 }
648 return &connection->daemon->default_handler; 654 return &connection->daemon->default_handler;
649} 655}
650 656
@@ -659,33 +665,33 @@ MHD_find_access_handler(struct MHD_Connection * connection) {
659 * @return MHD_YES if so 665 * @return MHD_YES if so
660 */ 666 */
661static int 667static int
662MHD_test_post_data(struct MHD_Connection * connection) { 668MHD_test_post_data (struct MHD_Connection *connection)
663 const char * encoding; 669{
664 void * buf; 670 const char *encoding;
671 void *buf;
665 672
666 if ( (connection->method == NULL) || 673 if ((connection->method == NULL) ||
667 (connection->response != NULL) || 674 (connection->response != NULL) ||
668 (0 != strcasecmp(connection->method, 675 (0 != strcasecmp (connection->method, MHD_HTTP_METHOD_POST)))
669 MHD_HTTP_METHOD_POST)) )
670 return MHD_NO; 676 return MHD_NO;
671 encoding = MHD_lookup_connection_value(connection, 677 encoding = MHD_lookup_connection_value (connection,
672 MHD_HEADER_KIND, 678 MHD_HEADER_KIND,
673 MHD_HTTP_HEADER_CONTENT_TYPE); 679 MHD_HTTP_HEADER_CONTENT_TYPE);
674 if (encoding == NULL) 680 if (encoding == NULL)
675 return MHD_NO; 681 return MHD_NO;
676 if ( (0 == strcasecmp(MHD_HTTP_POST_ENCODING_FORM_URLENCODED, 682 if ((0 == strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED,
677 encoding)) && 683 encoding)) && (connection->uploadSize != -1))
678 (connection->uploadSize != -1) ) { 684 {
679 buf = MHD_pool_reallocate(connection->pool, 685 buf = MHD_pool_reallocate (connection->pool,
680 connection->read_buffer, 686 connection->read_buffer,
681 connection->read_buffer_size, 687 connection->read_buffer_size,
682 connection->uploadSize + 1); 688 connection->uploadSize + 1);
683 if (buf == NULL) 689 if (buf == NULL)
684 return MHD_NO; 690 return MHD_NO;
685 connection->read_buffer_size = connection->uploadSize + 1; 691 connection->read_buffer_size = connection->uploadSize + 1;
686 connection->read_buffer = buf; 692 connection->read_buffer = buf;
687 return MHD_YES; 693 return MHD_YES;
688 } 694 }
689 return MHD_NO; 695 return MHD_NO;
690} 696}
691 697
@@ -704,47 +710,47 @@ MHD_test_post_data(struct MHD_Connection * connection) {
704 * memory). 710 * memory).
705 */ 711 */
706static int 712static int
707MHD_parse_post_data(struct MHD_Connection * connection) { 713MHD_parse_post_data (struct MHD_Connection *connection)
708 const char * encoding; 714{
715 const char *encoding;
709 int ret; 716 int ret;
710 717
711 encoding = MHD_lookup_connection_value(connection, 718 encoding = MHD_lookup_connection_value (connection,
712 MHD_HEADER_KIND, 719 MHD_HEADER_KIND,
713 MHD_HTTP_HEADER_CONTENT_TYPE); 720 MHD_HTTP_HEADER_CONTENT_TYPE);
714 if (encoding == NULL) 721 if (encoding == NULL)
715 return MHD_NO;
716 if (0 == strcasecmp(MHD_HTTP_POST_ENCODING_FORM_URLENCODED,
717 encoding)) {
718 ret = parse_arguments(MHD_POSTDATA_KIND,
719 connection,
720 connection->read_buffer);
721 /* invalidate read buffer for other uses --
722 in particular, do not give it to the
723 client; if this were to be needed, we would
724 have to make a copy, which would double memory
725 requirements */
726 connection->read_buffer_size = 0;
727 connection->readLoc = 0;
728 connection->uploadSize = 0;
729 connection->read_buffer = NULL;
730 return ret;
731 }
732 if (0 == strcasecmp(MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA,
733 encoding)) {
734 /* this code should never been reached right now,
735 since the test_post_data function would already
736 return MHD_NO; code is here only for future
737 extensions... */
738 /* see http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 */
739 MHD_DLOG(connection->daemon,
740 "Unsupported multipart encoding of POST data specified, not processing POST data.\n");
741 return MHD_NO; 722 return MHD_NO;
742 } 723 if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding))
724 {
725 ret = parse_arguments (MHD_POSTDATA_KIND,
726 connection, connection->read_buffer);
727 /* invalidate read buffer for other uses --
728 in particular, do not give it to the
729 client; if this were to be needed, we would
730 have to make a copy, which would double memory
731 requirements */
732 connection->read_buffer_size = 0;
733 connection->readLoc = 0;
734 connection->uploadSize = 0;
735 connection->read_buffer = NULL;
736 return ret;
737 }
738 if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding))
739 {
740 /* this code should never been reached right now,
741 since the test_post_data function would already
742 return MHD_NO; code is here only for future
743 extensions... */
744 /* see http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 */
745 MHD_DLOG (connection->daemon,
746 "Unsupported multipart encoding of POST data specified, not processing POST data.\n");
747 return MHD_NO;
748 }
743 /* this should never be reached, just here for 749 /* this should never be reached, just here for
744 error checking */ 750 error checking */
745 MHD_DLOG(connection->daemon, 751 MHD_DLOG (connection->daemon,
746 "Unknown encoding of POST data specified, not processing POST data.\n"); 752 "Unknown encoding of POST data specified, not processing POST data.\n");
747 return MHD_NO; 753 return MHD_NO;
748} 754}
749 755
750/** 756/**
@@ -752,46 +758,47 @@ MHD_parse_post_data(struct MHD_Connection * connection) {
752 * connection. 758 * connection.
753 */ 759 */
754void 760void
755MHD_call_connection_handler(struct MHD_Connection * connection) { 761MHD_call_connection_handler (struct MHD_Connection *connection)
756 struct MHD_Access_Handler * ah; 762{
763 struct MHD_Access_Handler *ah;
757 unsigned int processed; 764 unsigned int processed;
758 765
759 if (connection->response != NULL) 766 if (connection->response != NULL)
760 return; /* already queued a response */ 767 return; /* already queued a response */
761 if (connection->headersReceived == 0) 768 if (connection->headersReceived == 0)
762 abort(); /* bad timing... */ 769 abort (); /* bad timing... */
763 ah = MHD_find_access_handler(connection); 770 ah = MHD_find_access_handler (connection);
764 processed = connection->readLoc; 771 processed = connection->readLoc;
765 if (MHD_NO == ah->dh(ah->dh_cls, 772 if (MHD_NO == ah->dh (ah->dh_cls,
766 connection, 773 connection,
767 connection->url, 774 connection->url,
768 connection->method, 775 connection->method,
769 connection->version, 776 connection->version,
770 connection->read_buffer, 777 connection->read_buffer, &processed))
771 &processed)) { 778 {
772 /* serios internal error, close connection */ 779 /* serios internal error, close connection */
773 MHD_DLOG(connection->daemon, 780 MHD_DLOG (connection->daemon,
774 "Internal application error, closing connection.\n"); 781 "Internal application error, closing connection.\n");
775 CLOSE(connection->socket_fd); 782 CLOSE (connection->socket_fd);
776 connection->socket_fd = -1; 783 connection->socket_fd = -1;
777 return; 784 return;
778 } 785 }
779 /* dh left "processed" bytes in buffer for next time... */ 786 /* dh left "processed" bytes in buffer for next time... */
780 memmove(connection->read_buffer, 787 memmove (connection->read_buffer,
781 &connection->read_buffer[connection->readLoc - processed], 788 &connection->read_buffer[connection->readLoc - processed],
782 processed); 789 processed);
783 if (connection->uploadSize != -1) 790 if (connection->uploadSize != -1)
784 connection->uploadSize -= (connection->readLoc - processed); 791 connection->uploadSize -= (connection->readLoc - processed);
785 connection->readLoc = processed; 792 connection->readLoc = processed;
786 if ( (connection->uploadSize == 0) || 793 if ((connection->uploadSize == 0) ||
787 ( (connection->readLoc == 0) && 794 ((connection->readLoc == 0) &&
788 (connection->uploadSize == -1) && 795 (connection->uploadSize == -1) && (connection->socket_fd == -1)))
789 (connection->socket_fd == -1) ) ) { 796 {
790 connection->bodyReceived = 1; 797 connection->bodyReceived = 1;
791 connection->readLoc = 0; 798 connection->readLoc = 0;
792 connection->read_buffer_size = 0; 799 connection->read_buffer_size = 0;
793 connection->read_buffer = NULL; 800 connection->read_buffer = NULL;
794 } 801 }
795} 802}
796 803
797 804
@@ -802,81 +809,88 @@ MHD_call_connection_handler(struct MHD_Connection * connection) {
802 * to handle reads. 809 * to handle reads.
803 */ 810 */
804int 811int
805MHD_connection_handle_read(struct MHD_Connection * connection) { 812MHD_connection_handle_read (struct MHD_Connection *connection)
813{
806 int bytes_read; 814 int bytes_read;
807 void * tmp; 815 void *tmp;
808 816
809 if (connection->pool == NULL) 817 if (connection->pool == NULL)
810 connection->pool = MHD_pool_create(connection->daemon->pool_size); 818 connection->pool = MHD_pool_create (connection->daemon->pool_size);
811 if (connection->pool == NULL) { 819 if (connection->pool == NULL)
812 MHD_DLOG(connection->daemon, 820 {
813 "Failed to create memory pool!\n"); 821 MHD_DLOG (connection->daemon, "Failed to create memory pool!\n");
814 CLOSE(connection->socket_fd); 822 CLOSE (connection->socket_fd);
815 connection->socket_fd = -1; 823 connection->socket_fd = -1;
816 return MHD_NO;
817 }
818 if ( (connection->readLoc >= connection->read_buffer_size) &&
819 (connection->headersReceived == 0) ) {
820 /* need to grow read buffer */
821 tmp = MHD_pool_reallocate(connection->pool,
822 connection->read_buffer,
823 connection->read_buffer_size,
824 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE);
825 if (tmp == NULL) {
826 MHD_DLOG(connection->daemon,
827 "Not enough memory for reading headers!\n");
828 MHD_excessive_data_handler(connection,
829 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
830 return MHD_NO; 824 return MHD_NO;
831 } 825 }
832 connection->read_buffer = tmp; 826 if ((connection->readLoc >= connection->read_buffer_size) &&
833 connection->read_buffer_size = connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; 827 (connection->headersReceived == 0))
834 } 828 {
835 if (connection->readLoc >= connection->read_buffer_size) { 829 /* need to grow read buffer */
836 MHD_DLOG(connection->daemon, 830 tmp = MHD_pool_reallocate (connection->pool,
837 "Unexpected call to %s.\n", 831 connection->read_buffer,
838 __FUNCTION__); 832 connection->read_buffer_size,
839 return MHD_NO; 833 connection->read_buffer_size * 2 +
840 } 834 MHD_BUF_INC_SIZE);
841 bytes_read = RECV(connection->socket_fd, 835 if (tmp == NULL)
842 &connection->read_buffer[connection->readLoc], 836 {
843 connection->read_buffer_size - connection->readLoc, 837 MHD_DLOG (connection->daemon,
844 0); 838 "Not enough memory for reading headers!\n");
845 if (bytes_read < 0) { 839 MHD_excessive_data_handler (connection,
846 if (errno == EINTR) 840 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
841 return MHD_NO;
842 }
843 connection->read_buffer = tmp;
844 connection->read_buffer_size =
845 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
846 }
847 if (connection->readLoc >= connection->read_buffer_size)
848 {
849 MHD_DLOG (connection->daemon, "Unexpected call to %s.\n", __FUNCTION__);
847 return MHD_NO; 850 return MHD_NO;
848 MHD_DLOG(connection->daemon, 851 }
849 "Failed to receive data: %s\n", 852 bytes_read = RECV (connection->socket_fd,
850 STRERROR(errno)); 853 &connection->read_buffer[connection->readLoc],
851 CLOSE(connection->socket_fd); 854 connection->read_buffer_size - connection->readLoc, 0);
852 connection->socket_fd = -1; 855 if (bytes_read < 0)
853 return MHD_YES; 856 {
854 } 857 if (errno == EINTR)
855 if (bytes_read == 0) { 858 return MHD_NO;
856 /* other side closed connection */ 859 MHD_DLOG (connection->daemon,
857 connection->read_close = MHD_YES; 860 "Failed to receive data: %s\n", STRERROR (errno));
858 if (connection->readLoc > 0) 861 CLOSE (connection->socket_fd);
859 MHD_call_connection_handler(connection); 862 connection->socket_fd = -1;
860 shutdown(connection->socket_fd, SHUT_RD); 863 return MHD_YES;
861 return MHD_YES; 864 }
862 } 865 if (bytes_read == 0)
866 {
867 /* other side closed connection */
868 connection->read_close = MHD_YES;
869 if (connection->readLoc > 0)
870 MHD_call_connection_handler (connection);
871 shutdown (connection->socket_fd, SHUT_RD);
872 return MHD_YES;
873 }
863 connection->readLoc += bytes_read; 874 connection->readLoc += bytes_read;
864 if (connection->headersReceived == 0) { 875 if (connection->headersReceived == 0)
865 MHD_parse_connection_headers(connection); 876 {
866 if (connection->headersReceived == 1) { 877 MHD_parse_connection_headers (connection);
867 connection->post_processed = MHD_test_post_data(connection); 878 if (connection->headersReceived == 1)
879 {
880 connection->post_processed = MHD_test_post_data (connection);
881 }
882 }
883 if (connection->headersReceived == 1)
884 {
885 if ((connection->post_processed == MHD_YES) &&
886 (connection->uploadSize == connection->readLoc))
887 if (MHD_NO == MHD_parse_post_data (connection))
888 connection->post_processed = MHD_NO;
889 if (((connection->post_processed == MHD_NO) ||
890 (connection->read_buffer_size == connection->readLoc)) &&
891 (connection->method != NULL))
892 MHD_call_connection_handler (connection);
868 } 893 }
869 }
870 if (connection->headersReceived == 1) {
871 if ( (connection->post_processed == MHD_YES) &&
872 (connection->uploadSize == connection->readLoc) )
873 if (MHD_NO == MHD_parse_post_data(connection))
874 connection->post_processed = MHD_NO;
875 if ( ( (connection->post_processed == MHD_NO) ||
876 (connection->read_buffer_size == connection->readLoc) ) &&
877 (connection->method != NULL) )
878 MHD_call_connection_handler(connection);
879 }
880 return MHD_YES; 894 return MHD_YES;
881} 895}
882 896
@@ -885,48 +899,51 @@ MHD_connection_handle_read(struct MHD_Connection * connection) {
885 * for http-compiliance. 899 * for http-compiliance.
886 */ 900 */
887static void 901static void
888MHD_add_extra_headers(struct MHD_Connection * connection) { 902MHD_add_extra_headers (struct MHD_Connection *connection)
889 const char * have; 903{
904 const char *have;
890 char buf[128]; 905 char buf[128];
891 906
892 if (connection->response->total_size == -1) { 907 if (connection->response->total_size == -1)
893 have = MHD_get_response_header(connection->response, 908 {
894 MHD_HTTP_HEADER_CONNECTION); 909 have = MHD_get_response_header (connection->response,
895 if (have == NULL) 910 MHD_HTTP_HEADER_CONNECTION);
896 MHD_add_response_header(connection->response, 911 if (have == NULL)
897 MHD_HTTP_HEADER_CONNECTION, 912 MHD_add_response_header (connection->response,
898 "close"); 913 MHD_HTTP_HEADER_CONNECTION, "close");
899 } else if (NULL == MHD_get_response_header(connection->response, 914 }
900 MHD_HTTP_HEADER_CONTENT_LENGTH)) { 915 else if (NULL == MHD_get_response_header (connection->response,
901 _REAL_SNPRINTF(buf, 916 MHD_HTTP_HEADER_CONTENT_LENGTH))
902 128, 917 {
903 "%llu", 918 _REAL_SNPRINTF (buf,
904 (unsigned long long) connection->response->total_size); 919 128,
905 MHD_add_response_header(connection->response, 920 "%llu",
906 MHD_HTTP_HEADER_CONTENT_LENGTH, 921 (unsigned long long) connection->response->total_size);
907 buf); 922 MHD_add_response_header (connection->response,
908 } 923 MHD_HTTP_HEADER_CONTENT_LENGTH, buf);
924 }
909} 925}
910 926
911static void get_date_string(char * date, 927static void
912 unsigned int max) { 928get_date_string (char *date, unsigned int max)
913 static const char * days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; 929{
914 static const char * mons[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; 930 static const char *days[] =
931 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
932 static const char *mons[] =
933 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
934"Nov", "Dec" };
915 struct tm now; 935 struct tm now;
916 time_t t; 936 time_t t;
917 937
918 time(&t); 938 time (&t);
919 gmtime_r(&t, &now); 939 gmtime_r (&t, &now);
920 snprintf(date, 940 snprintf (date,
921 max-1, 941 max - 1,
922 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n", 942 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
923 days[now.tm_wday % 7], 943 days[now.tm_wday % 7],
924 now.tm_mday, 944 now.tm_mday,
925 mons[now.tm_mon % 12], 945 mons[now.tm_mon % 12],
926 now.tm_year, 946 now.tm_year, now.tm_hour, now.tm_min, now.tm_sec);
927 now.tm_hour,
928 now.tm_min,
929 now.tm_sec);
930} 947}
931 948
932/** 949/**
@@ -935,62 +952,53 @@ static void get_date_string(char * date,
935 * HTTPd's response. 952 * HTTPd's response.
936 */ 953 */
937static int 954static int
938MHD_build_header_response(struct MHD_Connection * connection) { 955MHD_build_header_response (struct MHD_Connection *connection)
956{
939 size_t size; 957 size_t size;
940 size_t off; 958 size_t off;
941 struct MHD_HTTP_Header * pos; 959 struct MHD_HTTP_Header *pos;
942 char code[32]; 960 char code[32];
943 char date[128]; 961 char date[128];
944 char * data; 962 char *data;
945 963
946 MHD_add_extra_headers(connection); 964 MHD_add_extra_headers (connection);
947 SPRINTF(code, 965 SPRINTF (code, "%s %u\r\n", MHD_HTTP_VERSION_1_1, connection->responseCode);
948 "%s %u\r\n", 966 off = strlen (code);
949 MHD_HTTP_VERSION_1_1,
950 connection->responseCode);
951 off = strlen(code);
952 /* estimate size */ 967 /* estimate size */
953 size = off + 2; /* extra \r\n at the end */ 968 size = off + 2; /* extra \r\n at the end */
954 pos = connection->response->first_header; 969 pos = connection->response->first_header;
955 while (pos != NULL) { 970 while (pos != NULL)
956 size += strlen(pos->header) + strlen(pos->value) + 4; /* colon, space, linefeeds */ 971 {
957 pos = pos->next; 972 size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
958 } 973 pos = pos->next;
959 if (NULL == MHD_get_response_header(connection->response, 974 }
960 MHD_HTTP_HEADER_DATE)) 975 if (NULL == MHD_get_response_header (connection->response,
961 get_date_string(date, sizeof(date)); 976 MHD_HTTP_HEADER_DATE))
977 get_date_string (date, sizeof (date));
962 else 978 else
963 date[0] = '\0'; 979 date[0] = '\0';
964 size += strlen(date); 980 size += strlen (date);
965 /* produce data */ 981 /* produce data */
966 data = MHD_pool_allocate(connection->pool, 982 data = MHD_pool_allocate (connection->pool, size + 1, MHD_YES);
967 size + 1, 983 if (data == NULL)
968 MHD_YES); 984 {
969 if (data == NULL) { 985 MHD_DLOG (connection->daemon, "Not enough memory for write!\n");
970 MHD_DLOG(connection->daemon, 986 return MHD_NO;
971 "Not enough memory for write!\n"); 987 }
972 return MHD_NO; 988 memcpy (data, code, off);
973 }
974 memcpy(data,
975 code,
976 off);
977 pos = connection->response->first_header; 989 pos = connection->response->first_header;
978 while (pos != NULL) { 990 while (pos != NULL)
979 SPRINTF(&data[off], 991 {
980 "%s: %s\r\n", 992 SPRINTF (&data[off], "%s: %s\r\n", pos->header, pos->value);
981 pos->header, 993 off += strlen (pos->header) + strlen (pos->value) + 4;
982 pos->value); 994 pos = pos->next;
983 off += strlen(pos->header) + strlen(pos->value) + 4; 995 }
984 pos = pos->next; 996 strcpy (&data[off], date);
985 } 997 off += strlen (date);
986 strcpy(&data[off], 998 sprintf (&data[off], "\r\n");
987 date);
988 off += strlen(date);
989 sprintf(&data[off],
990 "\r\n");
991 off += 2; 999 off += 2;
992 if (off != size) 1000 if (off != size)
993 abort(); 1001 abort ();
994 connection->write_buffer = data; 1002 connection->write_buffer = data;
995 connection->writeLoc = size; 1003 connection->writeLoc = size;
996 connection->writePos = 0; 1004 connection->writePos = 0;
@@ -1005,159 +1013,164 @@ MHD_build_header_response(struct MHD_Connection * connection) {
1005 * call this function 1013 * call this function
1006 */ 1014 */
1007int 1015int
1008MHD_connection_handle_write(struct MHD_Connection * connection) { 1016MHD_connection_handle_write (struct MHD_Connection *connection)
1009 struct MHD_Response * response; 1017{
1018 struct MHD_Response *response;
1010 int ret; 1019 int ret;
1011 1020
1012 if (MHD_need_100_continue(connection)) { 1021 if (MHD_need_100_continue (connection))
1013 ret = SEND(connection->socket_fd, 1022 {
1014 &HTTP_100_CONTINUE[connection->continuePos], 1023 ret = SEND (connection->socket_fd,
1015 strlen(HTTP_100_CONTINUE) - connection->continuePos, 1024 &HTTP_100_CONTINUE[connection->continuePos],
1016 0); 1025 strlen (HTTP_100_CONTINUE) - connection->continuePos, 0);
1017 if (ret < 0) { 1026 if (ret < 0)
1018 if (errno == EINTR) 1027 {
1019 return MHD_YES; 1028 if (errno == EINTR)
1020 MHD_DLOG(connection->daemon, 1029 return MHD_YES;
1021 "Failed to send data: %s\n", 1030 MHD_DLOG (connection->daemon,
1022 STRERROR(errno)); 1031 "Failed to send data: %s\n", STRERROR (errno));
1023 CLOSE(connection->socket_fd); 1032 CLOSE (connection->socket_fd);
1024 connection->socket_fd = -1; 1033 connection->socket_fd = -1;
1034 return MHD_YES;
1035 }
1036 connection->continuePos += ret;
1025 return MHD_YES; 1037 return MHD_YES;
1026 } 1038 }
1027 connection->continuePos += ret;
1028 return MHD_YES;
1029 }
1030 response = connection->response; 1039 response = connection->response;
1031 if(response == NULL) { 1040 if (response == NULL)
1032 MHD_DLOG(connection->daemon, 1041 {
1033 "Unexpected call to %s.\n", 1042 MHD_DLOG (connection->daemon, "Unexpected call to %s.\n", __FUNCTION__);
1034 __FUNCTION__); 1043 return MHD_NO;
1035 return MHD_NO;
1036 }
1037 if (! connection->headersSent) {
1038 if ( (connection->write_buffer == NULL) &&
1039 (MHD_NO == MHD_build_header_response(connection)) ) {
1040 /* oops - close! */
1041 CLOSE(connection->socket_fd);
1042 connection->socket_fd = -1;
1043 return MHD_NO;
1044 } 1044 }
1045 ret = SEND(connection->socket_fd, 1045 if (!connection->headersSent)
1046 &connection->write_buffer[connection->writePos], 1046 {
1047 connection->writeLoc - connection->writePos, 1047 if ((connection->write_buffer == NULL) &&
1048 0); 1048 (MHD_NO == MHD_build_header_response (connection)))
1049 if (ret < 0) { 1049 {
1050 if (errno == EINTR) 1050 /* oops - close! */
1051 return MHD_YES; 1051 CLOSE (connection->socket_fd);
1052 MHD_DLOG(connection->daemon, 1052 connection->socket_fd = -1;
1053 "Failed to send data: %s\n", 1053 return MHD_NO;
1054 STRERROR(errno)); 1054 }
1055 CLOSE(connection->socket_fd); 1055 ret = SEND (connection->socket_fd,
1056 connection->socket_fd = -1; 1056 &connection->write_buffer[connection->writePos],
1057 connection->writeLoc - connection->writePos, 0);
1058 if (ret < 0)
1059 {
1060 if (errno == EINTR)
1061 return MHD_YES;
1062 MHD_DLOG (connection->daemon,
1063 "Failed to send data: %s\n", STRERROR (errno));
1064 CLOSE (connection->socket_fd);
1065 connection->socket_fd = -1;
1066 return MHD_YES;
1067 }
1068 connection->writePos += ret;
1069 if (connection->writeLoc == connection->writePos)
1070 {
1071 connection->writeLoc = 0;
1072 connection->writePos = 0;
1073 connection->headersSent = 1;
1074 MHD_pool_reallocate (connection->pool,
1075 connection->write_buffer,
1076 connection->write_buffer_size, 0);
1077 connection->write_buffer = NULL;
1078 connection->write_buffer_size = 0;
1079 }
1057 return MHD_YES; 1080 return MHD_YES;
1058 } 1081 }
1059 connection->writePos += ret;
1060 if (connection->writeLoc == connection->writePos) {
1061 connection->writeLoc = 0;
1062 connection->writePos = 0;
1063 connection->headersSent = 1;
1064 MHD_pool_reallocate(connection->pool,
1065 connection->write_buffer,
1066 connection->write_buffer_size,
1067 0);
1068 connection->write_buffer = NULL;
1069 connection->write_buffer_size = 0;
1070 }
1071 return MHD_YES;
1072 }
1073 if (response->total_size < connection->messagePos) 1082 if (response->total_size < connection->messagePos)
1074 abort(); /* internal error */ 1083 abort (); /* internal error */
1075 if (response->crc != NULL) 1084 if (response->crc != NULL)
1076 pthread_mutex_lock(&response->mutex); 1085 pthread_mutex_lock (&response->mutex);
1077 1086
1078 /* prepare send buffer */ 1087 /* prepare send buffer */
1079 if ( (response->crc != NULL) && 1088 if ((response->crc != NULL) &&
1080 ( (response->data_start > connection->messagePos) || 1089 ((response->data_start > connection->messagePos) ||
1081 (response->data_start + response->data_size <= connection->messagePos) ) ) { 1090 (response->data_start + response->data_size <=
1082 ret = response->crc(response->crc_cls, 1091 connection->messagePos)))
1083 connection->messagePos, 1092 {
1084 response->data, 1093 ret = response->crc (response->crc_cls,
1085 MIN(response->data_buffer_size, 1094 connection->messagePos,
1086 response->total_size - connection->messagePos)); 1095 response->data,
1087 if (ret == -1) { 1096 MIN (response->data_buffer_size,
1088 /* end of message, signal other side by closing! */ 1097 response->total_size -
1089 response->total_size = connection->messagePos; 1098 connection->messagePos));
1090 CLOSE(connection->socket_fd); 1099 if (ret == -1)
1091 connection->socket_fd = -1; 1100 {
1092 if (response->crc != NULL) 1101 /* end of message, signal other side by closing! */
1093 pthread_mutex_unlock(&response->mutex); 1102 response->total_size = connection->messagePos;
1094 return MHD_YES; 1103 CLOSE (connection->socket_fd);
1095 } 1104 connection->socket_fd = -1;
1096 response->data_start = connection->messagePos; 1105 if (response->crc != NULL)
1097 response->data_size = ret; 1106 pthread_mutex_unlock (&response->mutex);
1098 if (ret == 0) { 1107 return MHD_YES;
1099 if (response->crc != NULL) 1108 }
1100 pthread_mutex_unlock(&response->mutex); 1109 response->data_start = connection->messagePos;
1101 return MHD_YES; 1110 response->data_size = ret;
1111 if (ret == 0)
1112 {
1113 if (response->crc != NULL)
1114 pthread_mutex_unlock (&response->mutex);
1115 return MHD_YES;
1116 }
1102 } 1117 }
1103 }
1104 /* transmit */ 1118 /* transmit */
1105 ret = SEND(connection->socket_fd, 1119 ret = SEND (connection->socket_fd,
1106 &response->data[connection->messagePos - response->data_start], 1120 &response->data[connection->messagePos - response->data_start],
1107 response->data_size - (connection->messagePos - response->data_start), 1121 response->data_size - (connection->messagePos -
1108 0); 1122 response->data_start), 0);
1109 if (response->crc != NULL) 1123 if (response->crc != NULL)
1110 pthread_mutex_unlock(&response->mutex); 1124 pthread_mutex_unlock (&response->mutex);
1111 if (ret < 0) { 1125 if (ret < 0)
1112 if (errno == EINTR) 1126 {
1127 if (errno == EINTR)
1128 return MHD_YES;
1129 MHD_DLOG (connection->daemon,
1130 "Failed to send data: %s\n", STRERROR (errno));
1131 CLOSE (connection->socket_fd);
1132 connection->socket_fd = -1;
1113 return MHD_YES; 1133 return MHD_YES;
1114 MHD_DLOG(connection->daemon, 1134 }
1115 "Failed to send data: %s\n",
1116 STRERROR(errno));
1117 CLOSE(connection->socket_fd);
1118 connection->socket_fd = -1;
1119 return MHD_YES;
1120 }
1121 connection->messagePos += ret; 1135 connection->messagePos += ret;
1122 if (connection->messagePos > response->total_size) 1136 if (connection->messagePos > response->total_size)
1123 abort(); /* internal error */ 1137 abort (); /* internal error */
1124 if (connection->messagePos == response->total_size) { 1138 if (connection->messagePos == response->total_size)
1125 if ( (connection->bodyReceived == 0) || 1139 {
1126 (connection->headersReceived == 0) ) 1140 if ((connection->bodyReceived == 0) ||
1127 abort(); /* internal error */ 1141 (connection->headersReceived == 0))
1128 MHD_destroy_response(response); 1142 abort (); /* internal error */
1129 connection->continuePos = 0; 1143 MHD_destroy_response (response);
1130 connection->responseCode = 0; 1144 connection->continuePos = 0;
1131 connection->response = NULL; 1145 connection->responseCode = 0;
1132 connection->headers_received = NULL; 1146 connection->response = NULL;
1133 connection->headersReceived = 0; 1147 connection->headers_received = NULL;
1134 connection->headersSent = 0; 1148 connection->headersReceived = 0;
1135 connection->bodyReceived = 0; 1149 connection->headersSent = 0;
1136 connection->messagePos = 0; 1150 connection->bodyReceived = 0;
1137 connection->method = NULL; 1151 connection->messagePos = 0;
1138 connection->url = NULL; 1152 connection->method = NULL;
1139 if ( (connection->read_close == MHD_YES) || 1153 connection->url = NULL;
1140 (0 != strcasecmp(MHD_HTTP_VERSION_1_1, 1154 if ((connection->read_close == MHD_YES) ||
1141 connection->version)) ) { 1155 (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
1142 /* closed for reading => close for good! */ 1156 {
1143 if (connection->socket_fd != -1) 1157 /* closed for reading => close for good! */
1144 CLOSE(connection->socket_fd); 1158 if (connection->socket_fd != -1)
1145 connection->socket_fd = -1; 1159 CLOSE (connection->socket_fd);
1160 connection->socket_fd = -1;
1161 }
1162 connection->version = NULL;
1163 connection->read_buffer = NULL;
1164 connection->write_buffer = NULL;
1165 connection->read_buffer_size = 0;
1166 connection->readLoc = 0;
1167 connection->write_buffer_size = 0;
1168 connection->writePos = 0;
1169 connection->writeLoc = 0;
1170 MHD_pool_destroy (connection->pool);
1171 connection->pool = NULL;
1146 } 1172 }
1147 connection->version = NULL;
1148 connection->read_buffer = NULL;
1149 connection->write_buffer = NULL;
1150 connection->read_buffer_size = 0;
1151 connection->readLoc = 0;
1152 connection->write_buffer_size = 0;
1153 connection->writePos = 0;
1154 connection->writeLoc = 0;
1155 MHD_pool_destroy(connection->pool);
1156 connection->pool = NULL;
1157 }
1158 return MHD_YES; 1173 return MHD_YES;
1159} 1174}
1160 1175
1161/* end of connection.c */ 1176/* end of connection.c */
1162
1163
diff --git a/src/daemon/connection.h b/src/daemon/connection.h
index 840ae640..4955931d 100644
--- a/src/daemon/connection.h
+++ b/src/daemon/connection.h
@@ -35,19 +35,17 @@
35 * @return MHD_YES on success 35 * @return MHD_YES on success
36 */ 36 */
37int 37int
38MHD_connection_get_fdset(struct MHD_Connection * connection, 38MHD_connection_get_fdset (struct MHD_Connection *connection,
39 fd_set * read_fd_set, 39 fd_set * read_fd_set,
40 fd_set * write_fd_set, 40 fd_set * write_fd_set,
41 fd_set * except_fd_set, 41 fd_set * except_fd_set, int *max_fd);
42 int * max_fd);
43 42
44 43
45/** 44/**
46 * Call the handler of the application for this 45 * Call the handler of the application for this
47 * connection. 46 * connection.
48 */ 47 */
49void 48void MHD_call_connection_handler (struct MHD_Connection *connection);
50MHD_call_connection_handler(struct MHD_Connection * connection);
51 49
52/** 50/**
53 * This function handles a particular connection when it has been 51 * This function handles a particular connection when it has been
@@ -55,8 +53,7 @@ MHD_call_connection_handler(struct MHD_Connection * connection);
55 * (multithreaded, external select, internal select) call this function 53 * (multithreaded, external select, internal select) call this function
56 * to handle reads. 54 * to handle reads.
57 */ 55 */
58int 56int MHD_connection_handle_read (struct MHD_Connection *connection);
59MHD_connection_handle_read(struct MHD_Connection * connection);
60 57
61 58
62/** 59/**
@@ -65,8 +62,7 @@ MHD_connection_handle_read(struct MHD_Connection * connection);
65 * to be written, however, the function call does nothing. All implementations 62 * to be written, however, the function call does nothing. All implementations
66 * (multithreaded, external select, internal select) call this function 63 * (multithreaded, external select, internal select) call this function
67 */ 64 */
68int 65int MHD_connection_handle_write (struct MHD_Connection *connection);
69MHD_connection_handle_write(struct MHD_Connection * connection);
70 66
71 67
72#endif 68#endif
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c
index 2fbd3abc..3b2ebab0 100644
--- a/src/daemon/daemon.c
+++ b/src/daemon/daemon.c
@@ -48,30 +48,28 @@
48 * already exists 48 * already exists
49 */ 49 */
50int 50int
51MHD_register_handler(struct MHD_Daemon * daemon, 51MHD_register_handler (struct MHD_Daemon *daemon,
52 const char * uri_prefix, 52 const char *uri_prefix,
53 MHD_AccessHandlerCallback dh, 53 MHD_AccessHandlerCallback dh, void *dh_cls)
54 void * dh_cls) { 54{
55 struct MHD_Access_Handler * ah; 55 struct MHD_Access_Handler *ah;
56 56
57 if ( (daemon == NULL) || 57 if ((daemon == NULL) || (uri_prefix == NULL) || (dh == NULL))
58 (uri_prefix == NULL) || 58 return MHD_NO;
59 (dh == NULL) )
60 return MHD_NO;
61 ah = daemon->handlers; 59 ah = daemon->handlers;
62 while (ah != NULL) { 60 while (ah != NULL)
63 if (0 == strcmp(uri_prefix, 61 {
64 ah->uri_prefix)) 62 if (0 == strcmp (uri_prefix, ah->uri_prefix))
65 return MHD_NO; 63 return MHD_NO;
66 ah = ah->next; 64 ah = ah->next;
67 } 65 }
68 ah = malloc(sizeof(struct MHD_Access_Handler)); 66 ah = malloc (sizeof (struct MHD_Access_Handler));
69 ah->next = daemon->handlers; 67 ah->next = daemon->handlers;
70 ah->uri_prefix = strdup(uri_prefix); 68 ah->uri_prefix = strdup (uri_prefix);
71 ah->dh = dh; 69 ah->dh = dh;
72 ah->dh_cls = dh_cls; 70 ah->dh_cls = dh_cls;
73 daemon->handlers = ah; 71 daemon->handlers = ah;
74 return MHD_YES; 72 return MHD_YES;
75} 73}
76 74
77 75
@@ -84,34 +82,33 @@ MHD_register_handler(struct MHD_Daemon * daemon,
84 * is not known for this daemon 82 * is not known for this daemon
85 */ 83 */
86int 84int
87MHD_unregister_handler(struct MHD_Daemon * daemon, 85MHD_unregister_handler (struct MHD_Daemon *daemon,
88 const char * uri_prefix, 86 const char *uri_prefix,
89 MHD_AccessHandlerCallback dh, 87 MHD_AccessHandlerCallback dh, void *dh_cls)
90 void * dh_cls) { 88{
91 struct MHD_Access_Handler * prev; 89 struct MHD_Access_Handler *prev;
92 struct MHD_Access_Handler * pos; 90 struct MHD_Access_Handler *pos;
93 91
94 if ( (daemon == NULL) || 92 if ((daemon == NULL) || (uri_prefix == NULL) || (dh == NULL))
95 (uri_prefix == NULL) || 93 return MHD_NO;
96 (dh == NULL) )
97 return MHD_NO;
98 pos = daemon->handlers; 94 pos = daemon->handlers;
99 prev = NULL; 95 prev = NULL;
100 while (pos != NULL) { 96 while (pos != NULL)
101 if ( (dh == pos->dh) && 97 {
102 (dh_cls == pos->dh_cls) && 98 if ((dh == pos->dh) &&
103 (0 == strcmp(uri_prefix, 99 (dh_cls == pos->dh_cls) &&
104 pos->uri_prefix)) ) { 100 (0 == strcmp (uri_prefix, pos->uri_prefix)))
105 if (prev == NULL) 101 {
106 daemon->handlers = pos->next; 102 if (prev == NULL)
107 else 103 daemon->handlers = pos->next;
108 prev->next = pos->next; 104 else
109 free(pos); 105 prev->next = pos->next;
110 return MHD_YES; 106 free (pos);
107 return MHD_YES;
108 }
109 prev = pos;
110 pos = pos->next;
111 } 111 }
112 prev = pos;
113 pos = pos->next;
114 }
115 return MHD_NO; 112 return MHD_NO;
116} 113}
117 114
@@ -123,34 +120,32 @@ MHD_unregister_handler(struct MHD_Daemon * daemon,
123 * options for this call. 120 * options for this call.
124 */ 121 */
125int 122int
126MHD_get_fdset(struct MHD_Daemon * daemon, 123MHD_get_fdset (struct MHD_Daemon *daemon,
127 fd_set * read_fd_set, 124 fd_set * read_fd_set,
128 fd_set * write_fd_set, 125 fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd)
129 fd_set * except_fd_set, 126{
130 int * max_fd) { 127 struct MHD_Connection *pos;
131 struct MHD_Connection * pos; 128
132 129 if ((daemon == NULL) ||
133 if ( (daemon == NULL) || 130 (read_fd_set == NULL) ||
134 (read_fd_set == NULL) || 131 (write_fd_set == NULL) ||
135 (write_fd_set == NULL) || 132 (except_fd_set == NULL) ||
136 (except_fd_set == NULL) || 133 (max_fd == NULL) ||
137 (max_fd == NULL) || 134 ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0))
138 ( (daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0) ) 135 return MHD_NO;
139 return MHD_NO; 136 FD_SET (daemon->socket_fd, read_fd_set);
140 FD_SET(daemon->socket_fd, 137 if ((*max_fd) < daemon->socket_fd)
141 read_fd_set);
142 if ( (*max_fd) < daemon->socket_fd)
143 *max_fd = daemon->socket_fd; 138 *max_fd = daemon->socket_fd;
144 pos = daemon->connections; 139 pos = daemon->connections;
145 while (pos != NULL) { 140 while (pos != NULL)
146 if (MHD_YES != MHD_connection_get_fdset(pos, 141 {
147 read_fd_set, 142 if (MHD_YES != MHD_connection_get_fdset (pos,
148 write_fd_set, 143 read_fd_set,
149 except_fd_set, 144 write_fd_set,
150 max_fd)) 145 except_fd_set, max_fd))
151 return MHD_NO; 146 return MHD_NO;
152 pos = pos->next; 147 pos = pos->next;
153 } 148 }
154 return MHD_YES; 149 return MHD_YES;
155} 150}
156 151
@@ -160,8 +155,9 @@ MHD_get_fdset(struct MHD_Daemon * daemon,
160 * connection. 155 * connection.
161 */ 156 */
162static void * 157static void *
163MHD_handle_connection(void * data) { 158MHD_handle_connection (void *data)
164 struct MHD_Connection * con = data; 159{
160 struct MHD_Connection *con = data;
165 int num_ready; 161 int num_ready;
166 fd_set rs; 162 fd_set rs;
167 fd_set ws; 163 fd_set ws;
@@ -169,42 +165,35 @@ MHD_handle_connection(void * data) {
169 int max; 165 int max;
170 166
171 if (con == NULL) 167 if (con == NULL)
172 abort(); 168 abort ();
173 while ( (! con->daemon->shutdown) && 169 while ((!con->daemon->shutdown) && (con->socket_fd != -1))
174 (con->socket_fd != -1) ) { 170 {
175 FD_ZERO(&rs); 171 FD_ZERO (&rs);
176 FD_ZERO(&ws); 172 FD_ZERO (&ws);
177 FD_ZERO(&es); 173 FD_ZERO (&es);
178 max = 0; 174 max = 0;
179 MHD_connection_get_fdset(con, 175 MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
180 &rs, 176 num_ready = SELECT (max + 1, &rs, &ws, &es, NULL);
181 &ws, 177 if (num_ready <= 0)
182 &es, 178 {
183 &max); 179 if (errno == EINTR)
184 num_ready = SELECT(max + 1, 180 continue;
185 &rs, 181 break;
186 &ws, 182 }
187 &es, 183 if (((FD_ISSET (con->socket_fd, &rs)) &&
188 NULL); 184 (MHD_YES != MHD_connection_handle_read (con))) ||
189 if (num_ready <= 0) { 185 ((con->socket_fd != -1) &&
190 if (errno == EINTR) 186 (FD_ISSET (con->socket_fd, &ws)) &&
191 continue; 187 (MHD_YES != MHD_connection_handle_write (con))))
192 break; 188 break;
189 if ((con->headersReceived == 1) && (con->response == NULL))
190 MHD_call_connection_handler (con);
191 }
192 if (con->socket_fd != -1)
193 {
194 CLOSE (con->socket_fd);
195 con->socket_fd = -1;
193 } 196 }
194 if ( ( (FD_ISSET(con->socket_fd, &rs)) &&
195 (MHD_YES != MHD_connection_handle_read(con)) ) ||
196 ( (con->socket_fd != -1) &&
197 (FD_ISSET(con->socket_fd, &ws)) &&
198 (MHD_YES != MHD_connection_handle_write(con)) ) )
199 break;
200 if ( (con->headersReceived == 1) &&
201 (con->response == NULL) )
202 MHD_call_connection_handler(con);
203 }
204 if (con->socket_fd != -1) {
205 CLOSE(con->socket_fd);
206 con->socket_fd = -1;
207 }
208 return NULL; 197 return NULL;
209} 198}
210 199
@@ -215,77 +204,66 @@ MHD_handle_connection(void * data) {
215 * accept policy callback. 204 * accept policy callback.
216 */ 205 */
217static int 206static int
218MHD_accept_connection(struct MHD_Daemon * daemon) { 207MHD_accept_connection (struct MHD_Daemon *daemon)
219 struct MHD_Connection * connection; 208{
209 struct MHD_Connection *connection;
220 struct sockaddr_in6 addr6; 210 struct sockaddr_in6 addr6;
221 struct sockaddr * addr = (struct sockaddr*) &addr6; 211 struct sockaddr *addr = (struct sockaddr *) &addr6;
222 socklen_t addrlen; 212 socklen_t addrlen;
223 int s; 213 int s;
224 214
225 215
226 if (sizeof(struct sockaddr) > sizeof(struct sockaddr_in6)) 216 if (sizeof (struct sockaddr) > sizeof (struct sockaddr_in6))
227 abort(); /* fatal, serious error */ 217 abort (); /* fatal, serious error */
228 addrlen = sizeof(struct sockaddr_in6); 218 addrlen = sizeof (struct sockaddr_in6);
229 memset(addr, 219 memset (addr, 0, sizeof (struct sockaddr_in6));
230 0, 220 s = ACCEPT (daemon->socket_fd, addr, &addrlen);
231 sizeof(struct sockaddr_in6)); 221 if ((s < 0) || (addrlen <= 0))
232 s = ACCEPT(daemon->socket_fd, 222 {
233 addr, 223 MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));
234 &addrlen); 224 if (s != -1)
235 if ( (s < 0) || 225 CLOSE (s); /* just in case */
236 (addrlen <= 0) ) { 226 return MHD_NO;
237 MHD_DLOG(daemon, 227 }
238 "Error accepting connection: %s\n", 228 if (daemon->max_connections == 0)
239 STRERROR(errno)); 229 {
240 if (s != -1) 230 /* above connection limit - reject */
241 CLOSE(s); /* just in case */ 231 CLOSE (s);
242 return MHD_NO; 232 return MHD_NO;
243 } 233 }
244 if (daemon->max_connections == 0) { 234 if ((daemon->apc != NULL) &&
245 /* above connection limit - reject */ 235 (MHD_NO == daemon->apc (daemon->apc_cls, addr, addrlen)))
246 CLOSE(s); 236 {
247 return MHD_NO; 237 CLOSE (s);
248 } 238 return MHD_YES;
249 if ( (daemon->apc != NULL) && 239 }
250 (MHD_NO == daemon->apc(daemon->apc_cls, 240 connection = malloc (sizeof (struct MHD_Connection));
251 addr, 241 memset (connection, 0, sizeof (struct MHD_Connection));
252 addrlen)) ) {
253 CLOSE(s);
254 return MHD_YES;
255 }
256 connection = malloc(sizeof(struct MHD_Connection));
257 memset(connection,
258 0,
259 sizeof(struct MHD_Connection));
260 connection->pool = NULL; 242 connection->pool = NULL;
261 connection->addr = malloc(addrlen); 243 connection->addr = malloc (addrlen);
262 if (connection->addr == NULL) { 244 if (connection->addr == NULL)
263 CLOSE(s); 245 {
264 free(connection); 246 CLOSE (s);
265 return MHD_NO; 247 free (connection);
266 } 248 return MHD_NO;
267 memcpy(connection->addr, 249 }
268 addr, 250 memcpy (connection->addr, addr, addrlen);
269 addrlen);
270 connection->addr_len = addrlen; 251 connection->addr_len = addrlen;
271 connection->socket_fd = s; 252 connection->socket_fd = s;
272 connection->daemon = daemon; 253 connection->daemon = daemon;
273 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION) ) && 254 if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
274 (0 != pthread_create(&connection->pid, 255 (0 != pthread_create (&connection->pid,
275 NULL, 256 NULL, &MHD_handle_connection, connection)))
276 &MHD_handle_connection, 257 {
277 connection)) ) { 258 MHD_DLOG (daemon, "Failed to create a thread: %s\n", STRERROR (errno));
278 MHD_DLOG(daemon, 259 CLOSE (s);
279 "Failed to create a thread: %s\n", 260 free (connection->addr);
280 STRERROR(errno)); 261 free (connection);
281 CLOSE(s); 262 return MHD_NO;
282 free(connection->addr); 263 }
283 free(connection);
284 return MHD_NO;
285 }
286 connection->next = daemon->connections; 264 connection->next = daemon->connections;
287 daemon->connections = connection; 265 daemon->connections = connection;
288 daemon->max_connections--; 266 daemon->max_connections--;
289 return MHD_YES; 267 return MHD_YES;
290} 268}
291 269
@@ -301,43 +279,46 @@ MHD_accept_connection(struct MHD_Daemon * daemon) {
301 * the upload data buffer is full). 279 * the upload data buffer is full).
302 */ 280 */
303static void 281static void
304MHD_cleanup_connections(struct MHD_Daemon * daemon) { 282MHD_cleanup_connections (struct MHD_Daemon *daemon)
305 struct MHD_Connection * pos; 283{
306 struct MHD_Connection * prev; 284 struct MHD_Connection *pos;
307 void * unused; 285 struct MHD_Connection *prev;
286 void *unused;
308 287
309 pos = daemon->connections; 288 pos = daemon->connections;
310 prev = NULL; 289 prev = NULL;
311 while (pos != NULL) { 290 while (pos != NULL)
312 if (pos->socket_fd == -1) { 291 {
313 if (prev == NULL) 292 if (pos->socket_fd == -1)
314 daemon->connections = pos->next; 293 {
315 else 294 if (prev == NULL)
316 prev->next = pos->next; 295 daemon->connections = pos->next;
317 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) { 296 else
318 pthread_kill(pos->pid, SIGALRM); 297 prev->next = pos->next;
319 pthread_join(pos->pid, &unused); 298 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
320 } 299 {
321 if (pos->response != NULL) 300 pthread_kill (pos->pid, SIGALRM);
322 MHD_destroy_response(pos->response); 301 pthread_join (pos->pid, &unused);
323 MHD_pool_destroy(pos->pool); 302 }
324 free(pos->addr); 303 if (pos->response != NULL)
325 free(pos); 304 MHD_destroy_response (pos->response);
326 daemon->max_connections++; 305 MHD_pool_destroy (pos->pool);
327 if (prev == NULL) 306 free (pos->addr);
328 pos = daemon->connections; 307 free (pos);
329 else 308 daemon->max_connections++;
330 pos = prev->next; 309 if (prev == NULL)
331 continue; 310 pos = daemon->connections;
311 else
312 pos = prev->next;
313 continue;
314 }
315
316 if ((pos->headersReceived == 1) && (pos->response == NULL))
317 MHD_call_connection_handler (pos);
318
319 prev = pos;
320 pos = pos->next;
332 } 321 }
333
334 if ( (pos->headersReceived == 1) &&
335 (pos->response == NULL) )
336 MHD_call_connection_handler(pos);
337
338 prev = pos;
339 pos = pos->next;
340 }
341} 322}
342 323
343 324
@@ -348,9 +329,9 @@ MHD_cleanup_connections(struct MHD_Daemon * daemon) {
348 * @return MHD_NO on serious errors, MHD_YES on success 329 * @return MHD_NO on serious errors, MHD_YES on success
349 */ 330 */
350static int 331static int
351MHD_select(struct MHD_Daemon * daemon, 332MHD_select (struct MHD_Daemon *daemon, int may_block)
352 int may_block) { 333{
353 struct MHD_Connection * pos; 334 struct MHD_Connection *pos;
354 int num_ready; 335 int num_ready;
355 fd_set rs; 336 fd_set rs;
356 fd_set ws; 337 fd_set ws;
@@ -361,61 +342,58 @@ MHD_select(struct MHD_Daemon * daemon,
361 342
362 timeout.tv_sec = 0; 343 timeout.tv_sec = 0;
363 timeout.tv_usec = 0; 344 timeout.tv_usec = 0;
364 if(daemon == NULL) 345 if (daemon == NULL)
365 abort(); 346 abort ();
366 FD_ZERO(&rs); 347 FD_ZERO (&rs);
367 FD_ZERO(&ws); 348 FD_ZERO (&ws);
368 FD_ZERO(&es); 349 FD_ZERO (&es);
369 max = 0; 350 max = 0;
370 351
371 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) { 352 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
372 /* single-threaded, go over everything */ 353 {
373 if (MHD_NO == MHD_get_fdset(daemon, 354 /* single-threaded, go over everything */
374 &rs, 355 if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
375 &ws, 356 return MHD_NO;
376 &es, 357 }
377 &max)) 358 else
359 {
360 /* accept only, have one thread per connection */
361 max = daemon->socket_fd;
362 FD_SET (daemon->socket_fd, &rs);
363 }
364 num_ready = SELECT (max + 1,
365 &rs, &ws, &es, may_block == MHD_NO ? &timeout : NULL);
366 if (num_ready < 0)
367 {
368 if (errno == EINTR)
369 return MHD_YES;
370 MHD_DLOG (daemon, "Select failed: %s\n", STRERROR (errno));
378 return MHD_NO; 371 return MHD_NO;
379 } else { 372 }
380 /* accept only, have one thread per connection */
381 max = daemon->socket_fd;
382 FD_SET(daemon->socket_fd, &rs);
383 }
384 num_ready = SELECT(max + 1,
385 &rs,
386 &ws,
387 &es,
388 may_block == MHD_NO ? &timeout : NULL);
389 if (num_ready < 0) {
390 if (errno == EINTR)
391 return MHD_YES;
392 MHD_DLOG(daemon,
393 "Select failed: %s\n",
394 STRERROR(errno));
395 return MHD_NO;
396 }
397 ds = daemon->socket_fd; 373 ds = daemon->socket_fd;
398 if (ds == -1) 374 if (ds == -1)
399 return MHD_YES; 375 return MHD_YES;
400 if (FD_ISSET(ds, 376 if (FD_ISSET (ds, &rs))
401 &rs)) 377 MHD_accept_connection (daemon);
402 MHD_accept_connection(daemon); 378 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
403 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) { 379 {
404 /* do not have a thread per connection, process all connections now */ 380 /* do not have a thread per connection, process all connections now */
405 pos = daemon->connections; 381 pos = daemon->connections;
406 while (pos != NULL) { 382 while (pos != NULL)
407 ds = pos->socket_fd; 383 {
408 if (ds == -1) { 384 ds = pos->socket_fd;
409 pos = pos->next; 385 if (ds == -1)
410 continue; 386 {
411 } 387 pos = pos->next;
412 if (FD_ISSET(ds, &rs)) 388 continue;
413 MHD_connection_handle_read(pos); 389 }
414 if (FD_ISSET(ds, &ws)) 390 if (FD_ISSET (ds, &rs))
415 MHD_connection_handle_write(pos); 391 MHD_connection_handle_read (pos);
416 pos = pos->next; 392 if (FD_ISSET (ds, &ws))
393 MHD_connection_handle_write (pos);
394 pos = pos->next;
395 }
417 } 396 }
418 }
419 return MHD_YES; 397 return MHD_YES;
420} 398}
421 399
@@ -431,13 +409,14 @@ MHD_select(struct MHD_Daemon * daemon,
431 * options for this call. 409 * options for this call.
432 */ 410 */
433int 411int
434MHD_run(struct MHD_Daemon * daemon) { 412MHD_run (struct MHD_Daemon *daemon)
435 if ( (daemon->shutdown != 0) || 413{
436 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || 414 if ((daemon->shutdown != 0) ||
437 (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) ) 415 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
416 (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
438 return MHD_NO; 417 return MHD_NO;
439 MHD_select(daemon, MHD_NO); 418 MHD_select (daemon, MHD_NO);
440 MHD_cleanup_connections(daemon); 419 MHD_cleanup_connections (daemon);
441 return MHD_YES; 420 return MHD_YES;
442} 421}
443 422
@@ -447,12 +426,14 @@ MHD_run(struct MHD_Daemon * daemon) {
447 * is explicitly shut down. 426 * is explicitly shut down.
448 */ 427 */
449static void * 428static void *
450MHD_select_thread(void * cls) { 429MHD_select_thread (void *cls)
451 struct MHD_Daemon * daemon = cls; 430{
452 while (daemon->shutdown == 0) { 431 struct MHD_Daemon *daemon = cls;
453 MHD_select(daemon, MHD_YES); 432 while (daemon->shutdown == 0)
454 MHD_cleanup_connections(daemon); 433 {
455 } 434 MHD_select (daemon, MHD_YES);
435 MHD_cleanup_connections (daemon);
436 }
456 return NULL; 437 return NULL;
457} 438}
458 439
@@ -469,88 +450,75 @@ MHD_select_thread(void * cls) {
469 * @return NULL on error, handle to daemon on success 450 * @return NULL on error, handle to daemon on success
470 */ 451 */
471struct MHD_Daemon * 452struct MHD_Daemon *
472MHD_start_daemon(unsigned int options, 453MHD_start_daemon (unsigned int options,
473 unsigned short port, 454 unsigned short port,
474 MHD_AcceptPolicyCallback apc, 455 MHD_AcceptPolicyCallback apc,
475 void * apc_cls, 456 void *apc_cls,
476 MHD_AccessHandlerCallback dh, 457 MHD_AccessHandlerCallback dh, void *dh_cls, ...)
477 void * dh_cls, 458{
478 ...) {
479 const int on = 1; 459 const int on = 1;
480 struct MHD_Daemon * retVal; 460 struct MHD_Daemon *retVal;
481 int socket_fd; 461 int socket_fd;
482 struct sockaddr_in servaddr4; 462 struct sockaddr_in servaddr4;
483 struct sockaddr_in6 servaddr6; 463 struct sockaddr_in6 servaddr6;
484 const struct sockaddr * servaddr; 464 const struct sockaddr *servaddr;
485 socklen_t addrlen; 465 socklen_t addrlen;
486 va_list ap; 466 va_list ap;
487 enum MHD_OPTION opt; 467 enum MHD_OPTION opt;
488 468
489 if ((options & MHD_USE_SSL) != 0) 469 if ((options & MHD_USE_SSL) != 0)
490 return NULL; 470 return NULL;
491 if ( (port == 0) || 471 if ((port == 0) || (dh == NULL))
492 (dh == NULL) )
493 return NULL; 472 return NULL;
494 if ((options & MHD_USE_IPv6) != 0) 473 if ((options & MHD_USE_IPv6) != 0)
495 socket_fd = SOCKET(PF_INET6, SOCK_STREAM, 0); 474 socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0);
496 else 475 else
497 socket_fd = SOCKET(PF_INET, SOCK_STREAM, 0); 476 socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0);
498 if (socket_fd < 0) { 477 if (socket_fd < 0)
499 if ((options & MHD_USE_DEBUG) != 0) 478 {
500 fprintf(stderr, 479 if ((options & MHD_USE_DEBUG) != 0)
501 "Call to socket failed: %s\n", 480 fprintf (stderr, "Call to socket failed: %s\n", STRERROR (errno));
502 STRERROR(errno)); 481 return NULL;
503 return NULL; 482 }
504 } 483 if ((SETSOCKOPT (socket_fd,
505 if ( (SETSOCKOPT(socket_fd, 484 SOL_SOCKET,
506 SOL_SOCKET, 485 SO_REUSEADDR,
507 SO_REUSEADDR, 486 &on, sizeof (on)) < 0) && (options & MHD_USE_DEBUG) != 0)
508 &on, 487 fprintf (stderr, "setsockopt failed: %s\n", STRERROR (errno));
509 sizeof(on)) < 0) && 488 if ((options & MHD_USE_IPv6) != 0)
510 (options & MHD_USE_DEBUG) != 0) 489 {
511 fprintf(stderr, 490 memset (&servaddr6, 0, sizeof (struct sockaddr_in6));
512 "setsockopt failed: %s\n", 491 servaddr6.sin6_family = AF_INET6;
513 STRERROR(errno)); 492 servaddr6.sin6_port = htons (port);
514 if ((options & MHD_USE_IPv6) != 0) { 493 servaddr = (struct sockaddr *) &servaddr6;
515 memset(&servaddr6, 494 addrlen = sizeof (struct sockaddr_in6);
516 0, 495 }
517 sizeof(struct sockaddr_in6)); 496 else
518 servaddr6.sin6_family = AF_INET6; 497 {
519 servaddr6.sin6_port = htons(port); 498 memset (&servaddr4, 0, sizeof (struct sockaddr_in));
520 servaddr = (struct sockaddr*) &servaddr6; 499 servaddr4.sin_family = AF_INET;
521 addrlen = sizeof(struct sockaddr_in6); 500 servaddr4.sin_port = htons (port);
522 } else { 501 servaddr = (struct sockaddr *) &servaddr4;
523 memset(&servaddr4, 502 addrlen = sizeof (struct sockaddr_in);
524 0, 503 }
525 sizeof(struct sockaddr_in)); 504 if (BIND (socket_fd, servaddr, addrlen) < 0)
526 servaddr4.sin_family = AF_INET; 505 {
527 servaddr4.sin_port = htons(port); 506 if ((options & MHD_USE_DEBUG) != 0)
528 servaddr = (struct sockaddr*) &servaddr4; 507 fprintf (stderr,
529 addrlen = sizeof(struct sockaddr_in); 508 "Failed to bind to port %u: %s\n", port, STRERROR (errno));
530 } 509 CLOSE (socket_fd);
531 if (BIND(socket_fd, 510 return NULL;
532 servaddr, 511 }
533 addrlen) < 0) { 512 if (LISTEN (socket_fd, 20) < 0)
534 if ( (options & MHD_USE_DEBUG) != 0) 513 {
535 fprintf(stderr, 514 if ((options & MHD_USE_DEBUG) != 0)
536 "Failed to bind to port %u: %s\n", 515 fprintf (stderr,
537 port, 516 "Failed to listen for connections: %s\n", STRERROR (errno));
538 STRERROR(errno)); 517 CLOSE (socket_fd);
539 CLOSE(socket_fd); 518 return NULL;
540 return NULL; 519 }
541 } 520 retVal = malloc (sizeof (struct MHD_Daemon));
542 if (LISTEN(socket_fd, 20) < 0) { 521 memset (retVal, 0, sizeof (struct MHD_Daemon));
543 if ((options & MHD_USE_DEBUG) != 0)
544 fprintf(stderr,
545 "Failed to listen for connections: %s\n",
546 STRERROR(errno));
547 CLOSE(socket_fd);
548 return NULL;
549 }
550 retVal = malloc(sizeof(struct MHD_Daemon));
551 memset(retVal,
552 0,
553 sizeof(struct MHD_Daemon));
554 retVal->options = options; 522 retVal->options = options;
555 retVal->port = port; 523 retVal->port = port;
556 retVal->apc = apc; 524 retVal->apc = apc;
@@ -562,35 +530,34 @@ MHD_start_daemon(unsigned int options,
562 retVal->default_handler.next = NULL; 530 retVal->default_handler.next = NULL;
563 retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT; 531 retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
564 retVal->pool_size = MHD_POOL_SIZE_DEFAULT; 532 retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
565 va_start(ap, dh_cls); 533 va_start (ap, dh_cls);
566 while (MHD_OPTION_END != (opt = va_arg(ap, enum MHD_OPTION))) { 534 while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
567 switch (opt) { 535 {
568 case MHD_OPTION_CONNECTION_MEMORY_LIMIT: 536 switch (opt)
569 retVal->pool_size = va_arg(ap, unsigned int); 537 {
570 break; 538 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
571 case MHD_OPTION_CONNECTION_LIMIT: 539 retVal->pool_size = va_arg (ap, unsigned int);
572 retVal->max_connections = va_arg(ap, unsigned int); 540 break;
573 break; 541 case MHD_OPTION_CONNECTION_LIMIT:
574 default: 542 retVal->max_connections = va_arg (ap, unsigned int);
575 fprintf(stderr, 543 break;
576 "Invalid MHD_OPTION argument! (Did you terminate the list with MHD_OPTION_END?)\n"); 544 default:
577 abort(); 545 fprintf (stderr,
546 "Invalid MHD_OPTION argument! (Did you terminate the list with MHD_OPTION_END?)\n");
547 abort ();
548 }
549 }
550 va_end (ap);
551 if (((0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
552 (0 != (options & MHD_USE_SELECT_INTERNALLY))) &&
553 (0 != pthread_create (&retVal->pid, NULL, &MHD_select_thread, retVal)))
554 {
555 MHD_DLOG (retVal,
556 "Failed to create listen thread: %s\n", STRERROR (errno));
557 free (retVal);
558 CLOSE (socket_fd);
559 return NULL;
578 } 560 }
579 }
580 va_end(ap);
581 if ( ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
582 (0 != (options & MHD_USE_SELECT_INTERNALLY)) ) &&
583 (0 != pthread_create(&retVal->pid,
584 NULL,
585 &MHD_select_thread,
586 retVal)) ) {
587 MHD_DLOG(retVal,
588 "Failed to create listen thread: %s\n",
589 STRERROR(errno));
590 free(retVal);
591 CLOSE(socket_fd);
592 return NULL;
593 }
594 return retVal; 561 return retVal;
595} 562}
596 563
@@ -598,27 +565,31 @@ MHD_start_daemon(unsigned int options,
598 * Shutdown an http daemon. 565 * Shutdown an http daemon.
599 */ 566 */
600void 567void
601MHD_stop_daemon(struct MHD_Daemon * daemon) { 568MHD_stop_daemon (struct MHD_Daemon *daemon)
602 void * unused; 569{
570 void *unused;
603 571
604 if (daemon == NULL) 572 if (daemon == NULL)
605 return; 573 return;
606 daemon->shutdown = 1; 574 daemon->shutdown = 1;
607 CLOSE(daemon->socket_fd); 575 CLOSE (daemon->socket_fd);
608 daemon->socket_fd = -1; 576 daemon->socket_fd = -1;
609 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || 577 if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
610 (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) ) { 578 (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
611 pthread_kill(daemon->pid, SIGALRM); 579 {
612 pthread_join(daemon->pid, &unused); 580 pthread_kill (daemon->pid, SIGALRM);
613 } 581 pthread_join (daemon->pid, &unused);
614 while (daemon->connections != NULL) { 582 }
615 if (-1 != daemon->connections->socket_fd) { 583 while (daemon->connections != NULL)
616 CLOSE(daemon->connections->socket_fd); 584 {
617 daemon->connections->socket_fd = -1; 585 if (-1 != daemon->connections->socket_fd)
586 {
587 CLOSE (daemon->connections->socket_fd);
588 daemon->connections->socket_fd = -1;
589 }
590 MHD_cleanup_connections (daemon);
618 } 591 }
619 MHD_cleanup_connections(daemon); 592 free (daemon);
620 }
621 free(daemon);
622} 593}
623 594
624#ifndef WINDOWS 595#ifndef WINDOWS
@@ -627,23 +598,27 @@ static struct sigaction sig;
627 598
628static struct sigaction old; 599static struct sigaction old;
629 600
630static void sigalrmHandler(int sig) { 601static void
602sigalrmHandler (int sig)
603{
631} 604}
632 605
633/** 606/**
634 * Initialize the signal handler for SIGALRM. 607 * Initialize the signal handler for SIGALRM.
635 */ 608 */
636void __attribute__ ((constructor)) MHD_pthread_handlers_ltdl_init() { 609void __attribute__ ((constructor)) MHD_pthread_handlers_ltdl_init ()
610{
637 /* make sure SIGALRM does not kill us */ 611 /* make sure SIGALRM does not kill us */
638 memset(&sig, 0, sizeof(struct sigaction)); 612 memset (&sig, 0, sizeof (struct sigaction));
639 memset(&old, 0, sizeof(struct sigaction)); 613 memset (&old, 0, sizeof (struct sigaction));
640 sig.sa_flags = SA_NODEFER; 614 sig.sa_flags = SA_NODEFER;
641 sig.sa_handler = &sigalrmHandler; 615 sig.sa_handler = &sigalrmHandler;
642 sigaction(SIGALRM, &sig, &old); 616 sigaction (SIGALRM, &sig, &old);
643} 617}
644 618
645void __attribute__ ((destructor)) MHD_pthread_handlers_ltdl_fini() { 619void __attribute__ ((destructor)) MHD_pthread_handlers_ltdl_fini ()
646 sigaction(SIGALRM, &old, &sig); 620{
621 sigaction (SIGALRM, &old, &sig);
647} 622}
648 623
649#endif 624#endif
diff --git a/src/daemon/daemontest.c b/src/daemon/daemontest.c
index e7378cdd..7b4ad4de 100644
--- a/src/daemon/daemontest.c
+++ b/src/daemon/daemontest.c
@@ -31,131 +31,128 @@
31#include <string.h> 31#include <string.h>
32#include <stdio.h> 32#include <stdio.h>
33 33
34static int testStartError() { 34static int
35 struct MHD_Daemon * d; 35testStartError ()
36{
37 struct MHD_Daemon *d;
36 38
37 d = MHD_start_daemon(MHD_USE_DEBUG, 0, NULL, NULL, NULL, NULL); 39 d = MHD_start_daemon (MHD_USE_DEBUG, 0, NULL, NULL, NULL, NULL);
38 if (d != NULL) 40 if (d != NULL)
39 return 1; 41 return 1;
40 return 0; 42 return 0;
41} 43}
42 44
43static int apc_nothing(void * cls, 45static int
44 const struct sockaddr * addr, 46apc_nothing (void *cls, const struct sockaddr *addr, socklen_t addrlen)
45 socklen_t addrlen) { 47{
46 return MHD_NO; 48 return MHD_NO;
47} 49}
48 50
49static int apc_all(void * cls, 51static int
50 const struct sockaddr * addr, 52apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen)
51 socklen_t addrlen) { 53{
52 return MHD_YES; 54 return MHD_YES;
53} 55}
54 56
55static int ahc_nothing(void * cls, 57static int
56 struct MHD_Connection * connection, 58ahc_nothing (void *cls,
57 const char * url, 59 struct MHD_Connection *connection,
58 const char * method, 60 const char *url,
59 const char * version, 61 const char *method,
60 const char * upload_data, 62 const char *version,
61 unsigned int * upload_data_size) { 63 const char *upload_data, unsigned int *upload_data_size)
64{
62 return MHD_NO; 65 return MHD_NO;
63} 66}
64 67
65static int testStartStop() { 68static int
66 struct MHD_Daemon * d; 69testStartStop ()
70{
71 struct MHD_Daemon *d;
67 72
68 d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, 73 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
69 1080, 74 1080,
70 &apc_nothing, 75 &apc_nothing,
71 NULL, 76 NULL, &ahc_nothing, NULL, MHD_OPTION_END);
72 &ahc_nothing,
73 NULL,
74 MHD_OPTION_END);
75 if (d == NULL) 77 if (d == NULL)
76 return 2; 78 return 2;
77 MHD_stop_daemon(d); 79 MHD_stop_daemon (d);
78 return 0; 80 return 0;
79} 81}
80 82
81static int testExternalRun() { 83static int
82 struct MHD_Daemon * d; 84testExternalRun ()
85{
86 struct MHD_Daemon *d;
83 fd_set rs; 87 fd_set rs;
84 int maxfd; 88 int maxfd;
85 int i; 89 int i;
86 90
87 d = MHD_start_daemon(MHD_USE_DEBUG, 91 d = MHD_start_daemon (MHD_USE_DEBUG,
88 1081, 92 1081,
89 &apc_all, 93 &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
90 NULL,
91 &ahc_nothing,
92 NULL,
93 MHD_OPTION_END);
94 94
95 if (d == NULL) 95 if (d == NULL)
96 return 4; 96 return 4;
97 i = 0; 97 i = 0;
98 while(i < 15) { 98 while (i < 15)
99 maxfd = 0; 99 {
100 FD_ZERO(&rs); 100 maxfd = 0;
101 MHD_get_fdset(d, &rs, &rs, &rs, &maxfd); 101 FD_ZERO (&rs);
102 if (MHD_run(d) == MHD_NO) { 102 MHD_get_fdset (d, &rs, &rs, &rs, &maxfd);
103 MHD_stop_daemon(d); 103 if (MHD_run (d) == MHD_NO)
104 return 8; 104 {
105 MHD_stop_daemon (d);
106 return 8;
107 }
108 i++;
105 } 109 }
106 i++; 110 MHD_stop_daemon (d);
107 }
108 MHD_stop_daemon(d);
109 return 0; 111 return 0;
110} 112}
111 113
112static int testThread() { 114static int
113 struct MHD_Daemon * d; 115testThread ()
114 d = MHD_start_daemon(MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY, 116{
115 1082, 117 struct MHD_Daemon *d;
116 &apc_all, 118 d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY,
117 NULL, 119 1082,
118 &ahc_nothing, 120 &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
119 NULL,
120 MHD_OPTION_END);
121 121
122 if (d == NULL) 122 if (d == NULL)
123 return 16; 123 return 16;
124 if (MHD_run(d) != MHD_NO) 124 if (MHD_run (d) != MHD_NO)
125 return 32; 125 return 32;
126 MHD_stop_daemon(d); 126 MHD_stop_daemon (d);
127 return 0; 127 return 0;
128} 128}
129 129
130static int testMultithread() { 130static int
131 struct MHD_Daemon * d; 131testMultithread ()
132 d = MHD_start_daemon(MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION, 132{
133 1083, 133 struct MHD_Daemon *d;
134 &apc_all, 134 d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION,
135 NULL, 135 1083,
136 &ahc_nothing, 136 &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
137 NULL,
138 MHD_OPTION_END);
139 137
140 if (d == NULL) 138 if (d == NULL)
141 return 64; 139 return 64;
142 if (MHD_run(d) != MHD_NO) 140 if (MHD_run (d) != MHD_NO)
143 return 128; 141 return 128;
144 MHD_stop_daemon(d); 142 MHD_stop_daemon (d);
145 return 0; 143 return 0;
146} 144}
147 145
148int main(int argc, 146int
149 char * const * argv) { 147main (int argc, char *const *argv)
148{
150 unsigned int errorCount = 0; 149 unsigned int errorCount = 0;
151 errorCount += testStartError(); 150 errorCount += testStartError ();
152 errorCount += testStartStop(); 151 errorCount += testStartStop ();
153 errorCount += testExternalRun(); 152 errorCount += testExternalRun ();
154 errorCount += testThread(); 153 errorCount += testThread ();
155 errorCount += testMultithread(); 154 errorCount += testMultithread ();
156 if (errorCount != 0) 155 if (errorCount != 0)
157 fprintf(stderr, 156 fprintf (stderr, "Error (code: %u)\n", errorCount);
158 "Error (code: %u)\n", 157 return errorCount != 0; /* 0 == pass */
159 errorCount);
160 return errorCount != 0; /* 0 == pass */
161} 158}
diff --git a/src/daemon/daemontest_get.c b/src/daemon/daemontest_get.c
index 08de296d..f200a4c8 100644
--- a/src/daemon/daemontest_get.c
+++ b/src/daemon/daemontest_get.c
@@ -35,210 +35,167 @@
35 35
36static int oneone; 36static int oneone;
37 37
38struct CBC { 38struct CBC
39 char * buf; 39{
40 char *buf;
40 size_t pos; 41 size_t pos;
41 size_t size; 42 size_t size;
42}; 43};
43 44
44static size_t copyBuffer(void * ptr, 45static size_t
45 size_t size, 46copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
46 size_t nmemb, 47{
47 void * ctx) { 48 struct CBC *cbc = ctx;
48 struct CBC * cbc = ctx;
49 49
50 if (cbc->pos + size * nmemb > cbc->size) 50 if (cbc->pos + size * nmemb > cbc->size)
51 return 0; /* overflow */ 51 return 0; /* overflow */
52 memcpy(&cbc->buf[cbc->pos], 52 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
53 ptr,
54 size * nmemb);
55 cbc->pos += size * nmemb; 53 cbc->pos += size * nmemb;
56 return size * nmemb; 54 return size * nmemb;
57} 55}
58 56
59static int ahc_echo(void * cls, 57static int
60 struct MHD_Connection * connection, 58ahc_echo (void *cls,
61 const char * url, 59 struct MHD_Connection *connection,
62 const char * method, 60 const char *url,
63 const char * version, 61 const char *method,
64 const char * upload_data, 62 const char *version,
65 unsigned int * upload_data_size) { 63 const char *upload_data, unsigned int *upload_data_size)
66 const char * me = cls; 64{
67 struct MHD_Response * response; 65 const char *me = cls;
66 struct MHD_Response *response;
68 int ret; 67 int ret;
69 68
70 if (0 != strcmp(me, method)) 69 if (0 != strcmp (me, method))
71 return MHD_NO; /* unexpected method */ 70 return MHD_NO; /* unexpected method */
72 response = MHD_create_response_from_data(strlen(url), 71 response = MHD_create_response_from_data (strlen (url),
73 (void*) url, 72 (void *) url, MHD_NO, MHD_YES);
74 MHD_NO, 73 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
75 MHD_YES); 74 MHD_destroy_response (response);
76 ret = MHD_queue_response(connection,
77 MHD_HTTP_OK,
78 response);
79 MHD_destroy_response(response);
80 return ret; 75 return ret;
81} 76}
82 77
83 78
84static int testInternalGet() { 79static int
85 struct MHD_Daemon * d; 80testInternalGet ()
86 CURL * c; 81{
82 struct MHD_Daemon *d;
83 CURL *c;
87 char buf[2048]; 84 char buf[2048];
88 struct CBC cbc; 85 struct CBC cbc;
89 86
90 cbc.buf = buf; 87 cbc.buf = buf;
91 cbc.size = 2048; 88 cbc.size = 2048;
92 cbc.pos = 0; 89 cbc.pos = 0;
93 d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, 90 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
94 1080, 91 1080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
95 NULL,
96 NULL,
97 &ahc_echo,
98 "GET",
99 MHD_OPTION_END);
100 if (d == NULL) 92 if (d == NULL)
101 return 1; 93 return 1;
102 c = curl_easy_init(); 94 c = curl_easy_init ();
103 curl_easy_setopt(c, 95 curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world");
104 CURLOPT_URL, 96 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
105 "http://localhost:1080/hello_world"); 97 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
106 curl_easy_setopt(c, 98 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
107 CURLOPT_WRITEFUNCTION, 99 curl_easy_setopt (c, CURLOPT_TIMEOUT, 2L);
108 &copyBuffer); 100 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 2L);
109 curl_easy_setopt(c,
110 CURLOPT_WRITEDATA,
111 &cbc);
112 curl_easy_setopt(c,
113 CURLOPT_FAILONERROR,
114 1);
115 curl_easy_setopt(c,
116 CURLOPT_TIMEOUT,
117 2L);
118 curl_easy_setopt(c,
119 CURLOPT_CONNECTTIMEOUT,
120 2L);
121 if (oneone) 101 if (oneone)
122 curl_easy_setopt(c, 102 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
123 CURLOPT_HTTP_VERSION,
124 CURL_HTTP_VERSION_1_1);
125 else 103 else
126 curl_easy_setopt(c, 104 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
127 CURLOPT_HTTP_VERSION, 105 // NOTE: use of CONNECTTIMEOUT without also
128 CURL_HTTP_VERSION_1_0);
129 // NOTE: use of CONNECTTIMEOUT without also
130 // setting NOSIGNAL results in really weird 106 // setting NOSIGNAL results in really weird
131 // crashes on my system! 107 // crashes on my system!
132 curl_easy_setopt(c, 108 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
133 CURLOPT_NOSIGNAL, 109 if (CURLE_OK != curl_easy_perform (c))
134 1); 110 {
135 if (CURLE_OK != curl_easy_perform(c)) { 111 curl_easy_cleanup (c);
136 curl_easy_cleanup(c); 112 MHD_stop_daemon (d);
137 MHD_stop_daemon(d); 113 return 2;
138 return 2; 114 }
139 } 115 curl_easy_cleanup (c);
140 curl_easy_cleanup(c); 116 if (cbc.pos != strlen ("/hello_world"))
141 if (cbc.pos != strlen("/hello_world")) { 117 {
142 MHD_stop_daemon(d); 118 MHD_stop_daemon (d);
143 return 4; 119 return 4;
144 } 120 }
145 121
146 if (0 != strncmp("/hello_world", 122 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
147 cbc.buf, 123 {
148 strlen("/hello_world"))) { 124 MHD_stop_daemon (d);
149 MHD_stop_daemon(d); 125 return 8;
150 return 8; 126 }
151 } 127 MHD_stop_daemon (d);
152 MHD_stop_daemon(d);
153 128
154 return 0; 129 return 0;
155} 130}
156 131
157static int testMultithreadedGet() { 132static int
158 struct MHD_Daemon * d; 133testMultithreadedGet ()
159 CURL * c; 134{
135 struct MHD_Daemon *d;
136 CURL *c;
160 char buf[2048]; 137 char buf[2048];
161 struct CBC cbc; 138 struct CBC cbc;
162 139
163 cbc.buf = buf; 140 cbc.buf = buf;
164 cbc.size = 2048; 141 cbc.size = 2048;
165 cbc.pos = 0; 142 cbc.pos = 0;
166 d = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG, 143 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
167 1081, 144 1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
168 NULL,
169 NULL,
170 &ahc_echo,
171 "GET",
172 MHD_OPTION_END);
173 if (d == NULL) 145 if (d == NULL)
174 return 16; 146 return 16;
175 c = curl_easy_init(); 147 c = curl_easy_init ();
176 curl_easy_setopt(c, 148 curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
177 CURLOPT_URL, 149 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
178 "http://localhost:1081/hello_world"); 150 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
179 curl_easy_setopt(c, 151 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
180 CURLOPT_WRITEFUNCTION, 152 curl_easy_setopt (c, CURLOPT_TIMEOUT, 2L);
181 &copyBuffer);
182 curl_easy_setopt(c,
183 CURLOPT_WRITEDATA,
184 &cbc);
185 curl_easy_setopt(c,
186 CURLOPT_FAILONERROR,
187 1);
188 curl_easy_setopt(c,
189 CURLOPT_TIMEOUT,
190 2L);
191 if (oneone) 153 if (oneone)
192 curl_easy_setopt(c, 154 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
193 CURLOPT_HTTP_VERSION,
194 CURL_HTTP_VERSION_1_1);
195 else 155 else
196 curl_easy_setopt(c, 156 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
197 CURLOPT_HTTP_VERSION, 157 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 2L);
198 CURL_HTTP_VERSION_1_0);
199 curl_easy_setopt(c,
200 CURLOPT_CONNECTTIMEOUT,
201 2L);
202 // NOTE: use of CONNECTTIMEOUT without also 158 // NOTE: use of CONNECTTIMEOUT without also
203 // setting NOSIGNAL results in really weird 159 // setting NOSIGNAL results in really weird
204 // crashes on my system! 160 // crashes on my system!
205 curl_easy_setopt(c, 161 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
206 CURLOPT_NOSIGNAL, 162 if (CURLE_OK != curl_easy_perform (c))
207 1); 163 {
208 if (CURLE_OK != curl_easy_perform(c)) { 164 MHD_stop_daemon (d);
209 MHD_stop_daemon(d); 165 return 32;
210 return 32; 166 }
211 } 167 curl_easy_cleanup (c);
212 curl_easy_cleanup(c); 168 if (cbc.pos != strlen ("/hello_world"))
213 if (cbc.pos != strlen("/hello_world")) { 169 {
214 MHD_stop_daemon(d); 170 MHD_stop_daemon (d);
215 return 64; 171 return 64;
216 } 172 }
217 if (0 != strncmp("/hello_world", 173 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
218 cbc.buf, 174 {
219 strlen("/hello_world"))) { 175 MHD_stop_daemon (d);
220 MHD_stop_daemon(d); 176 return 128;
221 return 128; 177 }
222 } 178 MHD_stop_daemon (d);
223 MHD_stop_daemon(d);
224 179
225 return 0; 180 return 0;
226} 181}
227 182
228 183
229static int testExternalGet() { 184static int
230 struct MHD_Daemon * d; 185testExternalGet ()
231 CURL * c; 186{
187 struct MHD_Daemon *d;
188 CURL *c;
232 char buf[2048]; 189 char buf[2048];
233 struct CBC cbc; 190 struct CBC cbc;
234 CURLM * multi; 191 CURLM *multi;
235 CURLMcode mret; 192 CURLMcode mret;
236 fd_set rs; 193 fd_set rs;
237 fd_set ws; 194 fd_set ws;
238 fd_set es; 195 fd_set es;
239 int max; 196 int max;
240 int running; 197 int running;
241 struct CURLMsg * msg; 198 struct CURLMsg *msg;
242 time_t start; 199 time_t start;
243 struct timeval tv; 200 struct timeval tv;
244 201
@@ -246,154 +203,121 @@ static int testExternalGet() {
246 cbc.buf = buf; 203 cbc.buf = buf;
247 cbc.size = 2048; 204 cbc.size = 2048;
248 cbc.pos = 0; 205 cbc.pos = 0;
249 d = MHD_start_daemon(MHD_USE_DEBUG, 206 d = MHD_start_daemon (MHD_USE_DEBUG,
250 1082, 207 1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
251 NULL,
252 NULL,
253 &ahc_echo,
254 "GET",
255 MHD_OPTION_END);
256 if (d == NULL) 208 if (d == NULL)
257 return 256; 209 return 256;
258 c = curl_easy_init(); 210 c = curl_easy_init ();
259 curl_easy_setopt(c, 211 curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world");
260 CURLOPT_URL, 212 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
261 "http://localhost:1082/hello_world"); 213 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
262 curl_easy_setopt(c, 214 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
263 CURLOPT_WRITEFUNCTION,
264 &copyBuffer);
265 curl_easy_setopt(c,
266 CURLOPT_WRITEDATA,
267 &cbc);
268 curl_easy_setopt(c,
269 CURLOPT_FAILONERROR,
270 1);
271 if (oneone) 215 if (oneone)
272 curl_easy_setopt(c, 216 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
273 CURLOPT_HTTP_VERSION,
274 CURL_HTTP_VERSION_1_1);
275 else 217 else
276 curl_easy_setopt(c, 218 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
277 CURLOPT_HTTP_VERSION, 219 curl_easy_setopt (c, CURLOPT_TIMEOUT, 5L);
278 CURL_HTTP_VERSION_1_0); 220 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 5L);
279 curl_easy_setopt(c,
280 CURLOPT_TIMEOUT,
281 5L);
282 curl_easy_setopt(c,
283 CURLOPT_CONNECTTIMEOUT,
284 5L);
285 // NOTE: use of CONNECTTIMEOUT without also 221 // NOTE: use of CONNECTTIMEOUT without also
286 // setting NOSIGNAL results in really weird 222 // setting NOSIGNAL results in really weird
287 // crashes on my system! 223 // crashes on my system!
288 curl_easy_setopt(c, 224 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
289 CURLOPT_NOSIGNAL,
290 1);
291 225
292 226
293 multi = curl_multi_init(); 227 multi = curl_multi_init ();
294 if (multi == NULL) { 228 if (multi == NULL)
295 curl_easy_cleanup(c); 229 {
296 MHD_stop_daemon(d); 230 curl_easy_cleanup (c);
297 return 512; 231 MHD_stop_daemon (d);
298 } 232 return 512;
299 mret = curl_multi_add_handle(multi, c); 233 }
300 if (mret != CURLM_OK) { 234 mret = curl_multi_add_handle (multi, c);
301 curl_multi_cleanup(multi); 235 if (mret != CURLM_OK)
302 curl_easy_cleanup(c); 236 {
303 MHD_stop_daemon(d); 237 curl_multi_cleanup (multi);
304 return 1024; 238 curl_easy_cleanup (c);
305 } 239 MHD_stop_daemon (d);
306 start = time(NULL); 240 return 1024;
307 while ( (time(NULL) - start < 5) && 241 }
308 (multi != NULL) ) { 242 start = time (NULL);
309 max = 0; 243 while ((time (NULL) - start < 5) && (multi != NULL))
310 FD_ZERO(&rs); 244 {
311 FD_ZERO(&ws); 245 max = 0;
312 FD_ZERO(&es); 246 FD_ZERO (&rs);
313 curl_multi_perform(multi, &running); 247 FD_ZERO (&ws);
314 mret = curl_multi_fdset(multi, 248 FD_ZERO (&es);
315 &rs, 249 curl_multi_perform (multi, &running);
316 &ws, 250 mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
317 &es, 251 if (mret != CURLM_OK)
318 &max); 252 {
319 if (mret != CURLM_OK) { 253 curl_multi_remove_handle (multi, c);
320 curl_multi_remove_handle(multi, c); 254 curl_multi_cleanup (multi);
321 curl_multi_cleanup(multi); 255 curl_easy_cleanup (c);
322 curl_easy_cleanup(c); 256 MHD_stop_daemon (d);
323 MHD_stop_daemon(d); 257 return 2048;
324 return 2048; 258 }
259 if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
260 {
261 curl_multi_remove_handle (multi, c);
262 curl_multi_cleanup (multi);
263 curl_easy_cleanup (c);
264 MHD_stop_daemon (d);
265 return 4096;
266 }
267 tv.tv_sec = 0;
268 tv.tv_usec = 1000;
269 select (max + 1, &rs, &ws, &es, &tv);
270 curl_multi_perform (multi, &running);
271 if (running == 0)
272 {
273 msg = curl_multi_info_read (multi, &running);
274 if (msg == NULL)
275 break;
276 if (msg->msg == CURLMSG_DONE)
277 {
278 if (msg->data.result != CURLE_OK)
279 printf ("%s failed at %s:%d: `%s'\n",
280 "curl_multi_perform",
281 __FILE__,
282 __LINE__, curl_easy_strerror (msg->data.result));
283 curl_multi_remove_handle (multi, c);
284 curl_multi_cleanup (multi);
285 curl_easy_cleanup (c);
286 c = NULL;
287 multi = NULL;
288 }
289 }
290 MHD_run (d);
325 } 291 }
326 if (MHD_YES != MHD_get_fdset(d, 292 if (multi != NULL)
327 &rs, 293 {
328 &ws, 294 curl_multi_remove_handle (multi, c);
329 &es, 295 curl_easy_cleanup (c);
330 &max)) { 296 curl_multi_cleanup (multi);
331 curl_multi_remove_handle(multi, c);
332 curl_multi_cleanup(multi);
333 curl_easy_cleanup(c);
334 MHD_stop_daemon(d);
335 return 4096;
336 } 297 }
337 tv.tv_sec = 0; 298 MHD_stop_daemon (d);
338 tv.tv_usec = 1000; 299 if (cbc.pos != strlen ("/hello_world"))
339 select(max + 1,
340 &rs,
341 &ws,
342 &es,
343 &tv);
344 curl_multi_perform(multi, &running);
345 if (running == 0) {
346 msg = curl_multi_info_read(multi,
347 &running);
348 if (msg == NULL)
349 break;
350 if (msg->msg == CURLMSG_DONE) {
351 if (msg->data.result != CURLE_OK)
352 printf("%s failed at %s:%d: `%s'\n",
353 "curl_multi_perform",
354 __FILE__,
355 __LINE__,
356 curl_easy_strerror(msg->data.result));
357 curl_multi_remove_handle(multi, c);
358 curl_multi_cleanup(multi);
359 curl_easy_cleanup(c);
360 c = NULL;
361 multi = NULL;
362 }
363 }
364 MHD_run(d);
365 }
366 if (multi != NULL) {
367 curl_multi_remove_handle(multi, c);
368 curl_easy_cleanup(c);
369 curl_multi_cleanup(multi);
370 }
371 MHD_stop_daemon(d);
372 if (cbc.pos != strlen("/hello_world"))
373 return 8192; 300 return 8192;
374 if (0 != strncmp("/hello_world", 301 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
375 cbc.buf,
376 strlen("/hello_world")))
377 return 16384; 302 return 16384;
378 return 0; 303 return 0;
379} 304}
380 305
381 306
382 307
383int main(int argc, 308int
384 char * const * argv) { 309main (int argc, char *const *argv)
310{
385 unsigned int errorCount = 0; 311 unsigned int errorCount = 0;
386 312
387 oneone = NULL != strstr(argv[0], "11"); 313 oneone = NULL != strstr (argv[0], "11");
388 if (0 != curl_global_init(CURL_GLOBAL_WIN32)) 314 if (0 != curl_global_init (CURL_GLOBAL_WIN32))
389 return 2; 315 return 2;
390 errorCount += testInternalGet(); 316 errorCount += testInternalGet ();
391 errorCount += testMultithreadedGet(); 317 errorCount += testMultithreadedGet ();
392 errorCount += testExternalGet(); 318 errorCount += testExternalGet ();
393 if (errorCount != 0) 319 if (errorCount != 0)
394 fprintf(stderr, 320 fprintf (stderr, "Error (code: %u)\n", errorCount);
395 "Error (code: %u)\n", 321 curl_global_cleanup ();
396 errorCount); 322 return errorCount != 0; /* 0 == pass */
397 curl_global_cleanup();
398 return errorCount != 0; /* 0 == pass */
399} 323}
diff --git a/src/daemon/daemontest_long_header.c b/src/daemon/daemontest_long_header.c
index 48635704..d0e26484 100644
--- a/src/daemon/daemontest_long_header.c
+++ b/src/daemon/daemontest_long_header.c
@@ -41,247 +41,196 @@
41 41
42static int oneone; 42static int oneone;
43 43
44static int apc_all(void * cls, 44static int
45 const struct sockaddr * addr, 45apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen)
46 socklen_t addrlen) { 46{
47 return MHD_YES; 47 return MHD_YES;
48} 48}
49 49
50struct CBC { 50struct CBC
51 char * buf; 51{
52 char *buf;
52 size_t pos; 53 size_t pos;
53 size_t size; 54 size_t size;
54}; 55};
55 56
56static size_t copyBuffer(void * ptr, 57static size_t
57 size_t size, 58copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
58 size_t nmemb, 59{
59 void * ctx) {
60 return size * nmemb; 60 return size * nmemb;
61} 61}
62 62
63static int ahc_echo(void * cls, 63static int
64 struct MHD_Connection * connection, 64ahc_echo (void *cls,
65 const char * url, 65 struct MHD_Connection *connection,
66 const char * method, 66 const char *url,
67 const char * version, 67 const char *method,
68 const char * upload_data, 68 const char *version,
69 unsigned int * upload_data_size) { 69 const char *upload_data, unsigned int *upload_data_size)
70 const char * me = cls; 70{
71 struct MHD_Response * response; 71 const char *me = cls;
72 struct MHD_Response *response;
72 int ret; 73 int ret;
73 74
74 if (0 != strcmp(me, method)) 75 if (0 != strcmp (me, method))
75 return MHD_NO; /* unexpected method */ 76 return MHD_NO; /* unexpected method */
76 response = MHD_create_response_from_data(strlen(url), 77 response = MHD_create_response_from_data (strlen (url),
77 (void*) url, 78 (void *) url, MHD_NO, MHD_YES);
78 MHD_NO, 79 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
79 MHD_YES); 80 MHD_destroy_response (response);
80 ret = MHD_queue_response(connection,
81 MHD_HTTP_OK,
82 response);
83 MHD_destroy_response(response);
84 return ret; 81 return ret;
85} 82}
86 83
87 84
88static int testLongUrlGet() { 85static int
89 struct MHD_Daemon * d; 86testLongUrlGet ()
90 CURL * c; 87{
88 struct MHD_Daemon *d;
89 CURL *c;
91 char buf[2048]; 90 char buf[2048];
92 struct CBC cbc; 91 struct CBC cbc;
93 char * url; 92 char *url;
94 long code; 93 long code;
95 94
96 cbc.buf = buf; 95 cbc.buf = buf;
97 cbc.size = 2048; 96 cbc.size = 2048;
98 cbc.pos = 0; 97 cbc.pos = 0;
99 d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */, 98 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
100 1080, 99 1080,
101 &apc_all, 100 &apc_all,
102 NULL, 101 NULL,
103 &ahc_echo, 102 &ahc_echo,
104 "GET", 103 "GET",
105 MHD_OPTION_CONNECTION_MEMORY_LIMIT, 104 MHD_OPTION_CONNECTION_MEMORY_LIMIT,
106 VERY_LONG / 2, 105 VERY_LONG / 2, MHD_OPTION_END);
107 MHD_OPTION_END);
108 if (d == NULL) 106 if (d == NULL)
109 return 1; 107 return 1;
110 c = curl_easy_init(); 108 c = curl_easy_init ();
111 url = malloc(VERY_LONG); 109 url = malloc (VERY_LONG);
112 memset(url, 110 memset (url, 'a', VERY_LONG);
113 'a', 111 url[VERY_LONG - 1] = '\0';
114 VERY_LONG); 112 memcpy (url, "http://localhost:1080/", strlen ("http://localhost:1080/"));
115 url[VERY_LONG-1] = '\0'; 113 curl_easy_setopt (c, CURLOPT_URL, url);
116 memcpy(url, 114 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
117 "http://localhost:1080/", 115 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
118 strlen("http://localhost:1080/")); 116 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
119 curl_easy_setopt(c, 117 curl_easy_setopt (c, CURLOPT_TIMEOUT, 2L);
120 CURLOPT_URL, 118 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 2L);
121 url);
122 curl_easy_setopt(c,
123 CURLOPT_WRITEFUNCTION,
124 &copyBuffer);
125 curl_easy_setopt(c,
126 CURLOPT_WRITEDATA,
127 &cbc);
128 curl_easy_setopt(c,
129 CURLOPT_FAILONERROR,
130 1);
131 curl_easy_setopt(c,
132 CURLOPT_TIMEOUT,
133 2L);
134 curl_easy_setopt(c,
135 CURLOPT_CONNECTTIMEOUT,
136 2L);
137 if (oneone) 119 if (oneone)
138 curl_easy_setopt(c, 120 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
139 CURLOPT_HTTP_VERSION,
140 CURL_HTTP_VERSION_1_1);
141 else 121 else
142 curl_easy_setopt(c, 122 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
143 CURLOPT_HTTP_VERSION, 123 // NOTE: use of CONNECTTIMEOUT without also
144 CURL_HTTP_VERSION_1_0);
145 // NOTE: use of CONNECTTIMEOUT without also
146 // setting NOSIGNAL results in really weird 124 // setting NOSIGNAL results in really weird
147 // crashes on my system! 125 // crashes on my system!
148 curl_easy_setopt(c, 126 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
149 CURLOPT_NOSIGNAL, 127 if (CURLE_OK == curl_easy_perform (c))
150 1); 128 {
151 if (CURLE_OK == curl_easy_perform(c)) { 129 curl_easy_cleanup (c);
152 curl_easy_cleanup(c); 130 MHD_stop_daemon (d);
153 MHD_stop_daemon(d); 131 free (url);
154 free(url); 132 return 2;
155 return 2; 133 }
156 } 134 if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code))
157 if (CURLE_OK != curl_easy_getinfo(c, 135 {
158 CURLINFO_RESPONSE_CODE, 136 curl_easy_cleanup (c);
159 &code)) { 137 MHD_stop_daemon (d);
160 curl_easy_cleanup(c); 138 free (url);
161 MHD_stop_daemon(d); 139 return 4;
162 free(url); 140 }
163 return 4; 141 curl_easy_cleanup (c);
164 } 142 MHD_stop_daemon (d);
165 curl_easy_cleanup(c); 143 free (url);
166 MHD_stop_daemon(d);
167 free(url);
168 if (code != MHD_HTTP_REQUEST_URI_TOO_LONG) 144 if (code != MHD_HTTP_REQUEST_URI_TOO_LONG)
169 return 8; 145 return 8;
170 return 0; 146 return 0;
171} 147}
172 148
173 149
174static int testLongHeaderGet() { 150static int
175 struct MHD_Daemon * d; 151testLongHeaderGet ()
176 CURL * c; 152{
153 struct MHD_Daemon *d;
154 CURL *c;
177 char buf[2048]; 155 char buf[2048];
178 struct CBC cbc; 156 struct CBC cbc;
179 char * url; 157 char *url;
180 long code; 158 long code;
181 struct curl_slist * header = NULL; 159 struct curl_slist *header = NULL;
182 160
183 cbc.buf = buf; 161 cbc.buf = buf;
184 cbc.size = 2048; 162 cbc.size = 2048;
185 cbc.pos = 0; 163 cbc.pos = 0;
186 d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */, 164 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
187 1080, 165 1080,
188 &apc_all, 166 &apc_all,
189 NULL, 167 NULL,
190 &ahc_echo, 168 &ahc_echo,
191 "GET", 169 "GET",
192 MHD_OPTION_CONNECTION_MEMORY_LIMIT, 170 MHD_OPTION_CONNECTION_MEMORY_LIMIT,
193 VERY_LONG / 2, 171 VERY_LONG / 2, MHD_OPTION_END);
194 MHD_OPTION_END);
195 if (d == NULL) 172 if (d == NULL)
196 return 16; 173 return 16;
197 c = curl_easy_init(); 174 c = curl_easy_init ();
198 url = malloc(VERY_LONG); 175 url = malloc (VERY_LONG);
199 memset(url, 176 memset (url, 'a', VERY_LONG);
200 'a', 177 url[VERY_LONG - 1] = '\0';
201 VERY_LONG); 178 url[VERY_LONG / 2] = ':';
202 url[VERY_LONG-1] = '\0'; 179 url[VERY_LONG / 2 + 1] = ':';
203 url[VERY_LONG/2] = ':'; 180 header = curl_slist_append (header, url);
204 url[VERY_LONG/2+1] = ':'; 181
205 header = curl_slist_append(header, 182 curl_easy_setopt (c, CURLOPT_HTTPHEADER, header);
206 url); 183 curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world");
207 184 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
208 curl_easy_setopt(c, 185 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
209 CURLOPT_HTTPHEADER, 186 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
210 header); 187 curl_easy_setopt (c, CURLOPT_TIMEOUT, 2L);
211 curl_easy_setopt(c, 188 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 2L);
212 CURLOPT_URL,
213 "http://localhost:1080/hello_world");
214 curl_easy_setopt(c,
215 CURLOPT_WRITEFUNCTION,
216 &copyBuffer);
217 curl_easy_setopt(c,
218 CURLOPT_WRITEDATA,
219 &cbc);
220 curl_easy_setopt(c,
221 CURLOPT_FAILONERROR,
222 1);
223 curl_easy_setopt(c,
224 CURLOPT_TIMEOUT,
225 2L);
226 curl_easy_setopt(c,
227 CURLOPT_CONNECTTIMEOUT,
228 2L);
229 if (oneone) 189 if (oneone)
230 curl_easy_setopt(c, 190 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
231 CURLOPT_HTTP_VERSION,
232 CURL_HTTP_VERSION_1_1);
233 else 191 else
234 curl_easy_setopt(c, 192 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
235 CURLOPT_HTTP_VERSION, 193 // NOTE: use of CONNECTTIMEOUT without also
236 CURL_HTTP_VERSION_1_0);
237 // NOTE: use of CONNECTTIMEOUT without also
238 // setting NOSIGNAL results in really weird 194 // setting NOSIGNAL results in really weird
239 // crashes on my system! 195 // crashes on my system!
240 curl_easy_setopt(c, 196 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
241 CURLOPT_NOSIGNAL, 197 if (CURLE_OK == curl_easy_perform (c))
242 1); 198 {
243 if (CURLE_OK == curl_easy_perform(c)) { 199 curl_easy_cleanup (c);
244 curl_easy_cleanup(c); 200 MHD_stop_daemon (d);
245 MHD_stop_daemon(d); 201 curl_slist_free_all (header);
246 curl_slist_free_all(header); 202 free (url);
247 free(url); 203 return 32;
248 return 32; 204 }
249 } 205 if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code))
250 if (CURLE_OK != curl_easy_getinfo(c, 206 {
251 CURLINFO_RESPONSE_CODE, 207 curl_slist_free_all (header);
252 &code)) { 208 curl_easy_cleanup (c);
253 curl_slist_free_all(header); 209 MHD_stop_daemon (d);
254 curl_easy_cleanup(c); 210 free (url);
255 MHD_stop_daemon(d); 211 return 64;
256 free(url); 212 }
257 return 64; 213 curl_slist_free_all (header);
258 } 214 curl_easy_cleanup (c);
259 curl_slist_free_all(header); 215 MHD_stop_daemon (d);
260 curl_easy_cleanup(c); 216 free (url);
261 MHD_stop_daemon(d);
262 free(url);
263 if (code != MHD_HTTP_REQUEST_ENTITY_TOO_LARGE) 217 if (code != MHD_HTTP_REQUEST_ENTITY_TOO_LARGE)
264 return 128; 218 return 128;
265 return 0; 219 return 0;
266} 220}
267 221
268 222int
269 223main (int argc, char *const *argv)
270 224{
271
272int main(int argc,
273 char * const * argv) {
274 unsigned int errorCount = 0; 225 unsigned int errorCount = 0;
275 226
276 oneone = NULL != strstr(argv[0], "11"); 227 oneone = NULL != strstr (argv[0], "11");
277 if (0 != curl_global_init(CURL_GLOBAL_WIN32)) 228 if (0 != curl_global_init (CURL_GLOBAL_WIN32))
278 return 2; 229 return 2;
279 errorCount += testLongUrlGet(); 230 errorCount += testLongUrlGet ();
280 errorCount += testLongHeaderGet(); 231 errorCount += testLongHeaderGet ();
281 if (errorCount != 0) 232 if (errorCount != 0)
282 fprintf(stderr, 233 fprintf (stderr, "Error (code: %u)\n", errorCount);
283 "Error (code: %u)\n", 234 curl_global_cleanup ();
284 errorCount); 235 return errorCount != 0; /* 0 == pass */
285 curl_global_cleanup();
286 return errorCount != 0; /* 0 == pass */
287} 236}
diff --git a/src/daemon/daemontest_post.c b/src/daemon/daemontest_post.c
index 2c020563..61850a24 100644
--- a/src/daemon/daemontest_post.c
+++ b/src/daemon/daemontest_post.c
@@ -41,246 +41,187 @@
41 41
42static int oneone; 42static int oneone;
43 43
44struct CBC { 44struct CBC
45 char * buf; 45{
46 char *buf;
46 size_t pos; 47 size_t pos;
47 size_t size; 48 size_t size;
48}; 49};
49 50
50static size_t copyBuffer(void * ptr, 51static size_t
51 size_t size, 52copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
52 size_t nmemb, 53{
53 void * ctx) { 54 struct CBC *cbc = ctx;
54 struct CBC * cbc = ctx;
55 55
56 if (cbc->pos + size * nmemb > cbc->size) 56 if (cbc->pos + size * nmemb > cbc->size)
57 return 0; /* overflow */ 57 return 0; /* overflow */
58 memcpy(&cbc->buf[cbc->pos], 58 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
59 ptr,
60 size * nmemb);
61 cbc->pos += size * nmemb; 59 cbc->pos += size * nmemb;
62 return size * nmemb; 60 return size * nmemb;
63} 61}
64 62
65static int ahc_echo(void * cls, 63static int
66 struct MHD_Connection * connection, 64ahc_echo (void *cls,
67 const char * url, 65 struct MHD_Connection *connection,
68 const char * method, 66 const char *url,
69 const char * version, 67 const char *method,
70 const char * upload_data, 68 const char *version,
71 unsigned int * upload_data_size) { 69 const char *upload_data, unsigned int *upload_data_size)
72 struct MHD_Response * response; 70{
71 struct MHD_Response *response;
73 int ret; 72 int ret;
74 const char * r1; 73 const char *r1;
75 const char * r2; 74 const char *r2;
76 75
77 if (0 != strcmp("POST", method)) { 76 if (0 != strcmp ("POST", method))
78 printf("METHOD: %s\n", method); 77 {
79 return MHD_NO; /* unexpected method */ 78 printf ("METHOD: %s\n", method);
80 } 79 return MHD_NO; /* unexpected method */
81 r1 = MHD_lookup_connection_value(connection, 80 }
82 MHD_POSTDATA_KIND, 81 r1 = MHD_lookup_connection_value (connection, MHD_POSTDATA_KIND, "name");
83 "name"); 82 r2 = MHD_lookup_connection_value (connection, MHD_POSTDATA_KIND, "project");
84 r2 = MHD_lookup_connection_value(connection, 83 if ((r1 != NULL) &&
85 MHD_POSTDATA_KIND, 84 (r2 != NULL) &&
86 "project"); 85 (0 == strcmp ("daniel", r1)) && (0 == strcmp ("curl", r2)))
87 if ( (r1 != NULL) && 86 {
88 (r2 != NULL) && 87 response = MHD_create_response_from_data (strlen (url),
89 (0 == strcmp("daniel", 88 (void *) url,
90 r1)) && 89 MHD_NO, MHD_YES);
91 (0 == strcmp("curl", 90 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
92 r2)) ) { 91 MHD_destroy_response (response);
93 response = MHD_create_response_from_data(strlen(url), 92 return MHD_YES; /* done */
94 (void*) url, 93 }
95 MHD_NO,
96 MHD_YES);
97 ret = MHD_queue_response(connection,
98 MHD_HTTP_OK,
99 response);
100 MHD_destroy_response(response);
101 return MHD_YES; /* done */
102 }
103 return MHD_YES; 94 return MHD_YES;
104} 95}
105 96
106 97
107static int testInternalPost() { 98static int
108 struct MHD_Daemon * d; 99testInternalPost ()
109 CURL * c; 100{
101 struct MHD_Daemon *d;
102 CURL *c;
110 char buf[2048]; 103 char buf[2048];
111 struct CBC cbc; 104 struct CBC cbc;
112 105
113 cbc.buf = buf; 106 cbc.buf = buf;
114 cbc.size = 2048; 107 cbc.size = 2048;
115 cbc.pos = 0; 108 cbc.pos = 0;
116 d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, 109 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
117 1080, 110 1080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
118 NULL,
119 NULL,
120 &ahc_echo,
121 NULL,
122 MHD_OPTION_END);
123 if (d == NULL) 111 if (d == NULL)
124 return 1; 112 return 1;
125 c = curl_easy_init(); 113 c = curl_easy_init ();
126 curl_easy_setopt(c, 114 curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world");
127 CURLOPT_URL, 115 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
128 "http://localhost:1080/hello_world"); 116 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
129 curl_easy_setopt(c, 117 curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
130 CURLOPT_WRITEFUNCTION, 118 curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
131 &copyBuffer); 119 curl_easy_setopt (c, CURLOPT_POST, 1L);
132 curl_easy_setopt(c, 120 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
133 CURLOPT_WRITEDATA, 121 curl_easy_setopt (c, CURLOPT_TIMEOUT, 2L);
134 &cbc);
135 curl_easy_setopt(c,
136 CURLOPT_POSTFIELDS,
137 POST_DATA);
138 curl_easy_setopt(c,
139 CURLOPT_POSTFIELDSIZE,
140 strlen(POST_DATA));
141 curl_easy_setopt(c,
142 CURLOPT_POST,
143 1L);
144 curl_easy_setopt(c,
145 CURLOPT_FAILONERROR,
146 1);
147 curl_easy_setopt(c,
148 CURLOPT_TIMEOUT,
149 2L);
150 if (oneone) 122 if (oneone)
151 curl_easy_setopt(c, 123 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
152 CURLOPT_HTTP_VERSION,
153 CURL_HTTP_VERSION_1_1);
154 else 124 else
155 curl_easy_setopt(c, 125 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
156 CURLOPT_HTTP_VERSION, 126 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 2L);
157 CURL_HTTP_VERSION_1_0);
158 curl_easy_setopt(c,
159 CURLOPT_CONNECTTIMEOUT,
160 2L);
161 // NOTE: use of CONNECTTIMEOUT without also 127 // NOTE: use of CONNECTTIMEOUT without also
162 // setting NOSIGNAL results in really weird 128 // setting NOSIGNAL results in really weird
163 // crashes on my system! 129 // crashes on my system!
164 curl_easy_setopt(c, 130 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
165 CURLOPT_NOSIGNAL, 131 if (CURLE_OK != curl_easy_perform (c))
166 1); 132 {
167 if (CURLE_OK != curl_easy_perform(c)) { 133 curl_easy_cleanup (c);
168 curl_easy_cleanup(c); 134 MHD_stop_daemon (d);
169 MHD_stop_daemon(d); 135 return 2;
170 return 2; 136 }
171 } 137 curl_easy_cleanup (c);
172 curl_easy_cleanup(c); 138 if (cbc.pos != strlen ("/hello_world"))
173 if (cbc.pos != strlen("/hello_world")) { 139 {
174 MHD_stop_daemon(d); 140 MHD_stop_daemon (d);
175 return 4; 141 return 4;
176 } 142 }
177 143
178 if (0 != strncmp("/hello_world", 144 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
179 cbc.buf, 145 {
180 strlen("/hello_world"))) { 146 MHD_stop_daemon (d);
181 MHD_stop_daemon(d); 147 return 8;
182 return 8; 148 }
183 } 149 MHD_stop_daemon (d);
184 MHD_stop_daemon(d);
185 150
186 return 0; 151 return 0;
187} 152}
188 153
189static int testMultithreadedPost() { 154static int
190 struct MHD_Daemon * d; 155testMultithreadedPost ()
191 CURL * c; 156{
157 struct MHD_Daemon *d;
158 CURL *c;
192 char buf[2048]; 159 char buf[2048];
193 struct CBC cbc; 160 struct CBC cbc;
194 161
195 cbc.buf = buf; 162 cbc.buf = buf;
196 cbc.size = 2048; 163 cbc.size = 2048;
197 cbc.pos = 0; 164 cbc.pos = 0;
198 d = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION |MHD_USE_DEBUG, 165 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
199 1081, 166 1081, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
200 NULL,
201 NULL,
202 &ahc_echo,
203 NULL,
204 MHD_OPTION_END);
205 if (d == NULL) 167 if (d == NULL)
206 return 16; 168 return 16;
207 c = curl_easy_init(); 169 c = curl_easy_init ();
208 curl_easy_setopt(c, 170 curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
209 CURLOPT_URL, 171 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
210 "http://localhost:1081/hello_world"); 172 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
211 curl_easy_setopt(c, 173 curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
212 CURLOPT_WRITEFUNCTION, 174 curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
213 &copyBuffer); 175 curl_easy_setopt (c, CURLOPT_POST, 1L);
214 curl_easy_setopt(c, 176 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
215 CURLOPT_WRITEDATA, 177 curl_easy_setopt (c, CURLOPT_TIMEOUT, 2L);
216 &cbc);
217 curl_easy_setopt(c,
218 CURLOPT_POSTFIELDS,
219 POST_DATA);
220 curl_easy_setopt(c,
221 CURLOPT_POSTFIELDSIZE,
222 strlen(POST_DATA));
223 curl_easy_setopt(c,
224 CURLOPT_POST,
225 1L);
226 curl_easy_setopt(c,
227 CURLOPT_FAILONERROR,
228 1);
229 curl_easy_setopt(c,
230 CURLOPT_TIMEOUT,
231 2L);
232 if (oneone) 178 if (oneone)
233 curl_easy_setopt(c, 179 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
234 CURLOPT_HTTP_VERSION,
235 CURL_HTTP_VERSION_1_1);
236 else 180 else
237 curl_easy_setopt(c, 181 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
238 CURLOPT_HTTP_VERSION, 182 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 2L);
239 CURL_HTTP_VERSION_1_0);
240 curl_easy_setopt(c,
241 CURLOPT_CONNECTTIMEOUT,
242 2L);
243 // NOTE: use of CONNECTTIMEOUT without also 183 // NOTE: use of CONNECTTIMEOUT without also
244 // setting NOSIGNAL results in really weird 184 // setting NOSIGNAL results in really weird
245 // crashes on my system! 185 // crashes on my system!
246 curl_easy_setopt(c, 186 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
247 CURLOPT_NOSIGNAL, 187 if (CURLE_OK != curl_easy_perform (c))
248 1); 188 {
249 if (CURLE_OK != curl_easy_perform(c)) { 189 curl_easy_cleanup (c);
250 curl_easy_cleanup(c); 190 MHD_stop_daemon (d);
251 MHD_stop_daemon(d); 191 return 32;
252 return 32; 192 }
253 } 193 curl_easy_cleanup (c);
254 curl_easy_cleanup(c); 194 if (cbc.pos != strlen ("/hello_world"))
255 if (cbc.pos != strlen("/hello_world")) { 195 {
256 MHD_stop_daemon(d); 196 MHD_stop_daemon (d);
257 return 64; 197 return 64;
258 } 198 }
259 if (0 != strncmp("/hello_world", 199 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
260 cbc.buf, 200 {
261 strlen("/hello_world"))) { 201 MHD_stop_daemon (d);
262 MHD_stop_daemon(d); 202 return 128;
263 return 128; 203 }
264 } 204 MHD_stop_daemon (d);
265 MHD_stop_daemon(d);
266 205
267 return 0; 206 return 0;
268} 207}
269 208
270 209
271static int testExternalPost() { 210static int
272 struct MHD_Daemon * d; 211testExternalPost ()
273 CURL * c; 212{
213 struct MHD_Daemon *d;
214 CURL *c;
274 char buf[2048]; 215 char buf[2048];
275 struct CBC cbc; 216 struct CBC cbc;
276 CURLM * multi; 217 CURLM *multi;
277 CURLMcode mret; 218 CURLMcode mret;
278 fd_set rs; 219 fd_set rs;
279 fd_set ws; 220 fd_set ws;
280 fd_set es; 221 fd_set es;
281 int max; 222 int max;
282 int running; 223 int running;
283 struct CURLMsg * msg; 224 struct CURLMsg *msg;
284 time_t start; 225 time_t start;
285 struct timeval tv; 226 struct timeval tv;
286 227
@@ -288,163 +229,124 @@ static int testExternalPost() {
288 cbc.buf = buf; 229 cbc.buf = buf;
289 cbc.size = 2048; 230 cbc.size = 2048;
290 cbc.pos = 0; 231 cbc.pos = 0;
291 d = MHD_start_daemon(MHD_USE_DEBUG, 232 d = MHD_start_daemon (MHD_USE_DEBUG,
292 1082, 233 1082, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
293 NULL,
294 NULL,
295 &ahc_echo,
296 NULL,
297 MHD_OPTION_END);
298 if (d == NULL) 234 if (d == NULL)
299 return 256; 235 return 256;
300 c = curl_easy_init(); 236 c = curl_easy_init ();
301 curl_easy_setopt(c, 237 curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world");
302 CURLOPT_URL, 238 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
303 "http://localhost:1082/hello_world"); 239 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
304 curl_easy_setopt(c, 240 curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
305 CURLOPT_WRITEFUNCTION, 241 curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
306 &copyBuffer); 242 curl_easy_setopt (c, CURLOPT_POST, 1L);
307 curl_easy_setopt(c, 243 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
308 CURLOPT_WRITEDATA, 244 curl_easy_setopt (c, CURLOPT_TIMEOUT, 5L);
309 &cbc);
310 curl_easy_setopt(c,
311 CURLOPT_POSTFIELDS,
312 POST_DATA);
313 curl_easy_setopt(c,
314 CURLOPT_POSTFIELDSIZE,
315 strlen(POST_DATA));
316 curl_easy_setopt(c,
317 CURLOPT_POST,
318 1L);
319 curl_easy_setopt(c,
320 CURLOPT_FAILONERROR,
321 1);
322 curl_easy_setopt(c,
323 CURLOPT_TIMEOUT,
324 5L);
325 if (oneone) 245 if (oneone)
326 curl_easy_setopt(c, 246 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
327 CURLOPT_HTTP_VERSION,
328 CURL_HTTP_VERSION_1_1);
329 else 247 else
330 curl_easy_setopt(c, 248 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
331 CURLOPT_HTTP_VERSION, 249 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 5L);
332 CURL_HTTP_VERSION_1_0);
333 curl_easy_setopt(c,
334 CURLOPT_CONNECTTIMEOUT,
335 5L);
336 // NOTE: use of CONNECTTIMEOUT without also 250 // NOTE: use of CONNECTTIMEOUT without also
337 // setting NOSIGNAL results in really weird 251 // setting NOSIGNAL results in really weird
338 // crashes on my system! 252 // crashes on my system!
339 curl_easy_setopt(c, 253 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
340 CURLOPT_NOSIGNAL,
341 1);
342 254
343 255
344 multi = curl_multi_init(); 256 multi = curl_multi_init ();
345 if (multi == NULL) { 257 if (multi == NULL)
346 curl_easy_cleanup(c); 258 {
347 MHD_stop_daemon(d); 259 curl_easy_cleanup (c);
348 return 512; 260 MHD_stop_daemon (d);
349 } 261 return 512;
350 mret = curl_multi_add_handle(multi, c); 262 }
351 if (mret != CURLM_OK) { 263 mret = curl_multi_add_handle (multi, c);
352 curl_multi_cleanup(multi); 264 if (mret != CURLM_OK)
353 curl_easy_cleanup(c); 265 {
354 MHD_stop_daemon(d); 266 curl_multi_cleanup (multi);
355 return 1024; 267 curl_easy_cleanup (c);
356 } 268 MHD_stop_daemon (d);
357 start = time(NULL); 269 return 1024;
358 while ( (time(NULL) - start < 5) && 270 }
359 (multi != NULL) ) { 271 start = time (NULL);
360 max = 0; 272 while ((time (NULL) - start < 5) && (multi != NULL))
361 FD_ZERO(&rs); 273 {
362 FD_ZERO(&ws); 274 max = 0;
363 FD_ZERO(&es); 275 FD_ZERO (&rs);
364 curl_multi_perform(multi, &running); 276 FD_ZERO (&ws);
365 mret = curl_multi_fdset(multi, 277 FD_ZERO (&es);
366 &rs, 278 curl_multi_perform (multi, &running);
367 &ws, 279 mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
368 &es, 280 if (mret != CURLM_OK)
369 &max); 281 {
370 if (mret != CURLM_OK) { 282 curl_multi_remove_handle (multi, c);
371 curl_multi_remove_handle(multi, c); 283 curl_multi_cleanup (multi);
372 curl_multi_cleanup(multi); 284 curl_easy_cleanup (c);
373 curl_easy_cleanup(c); 285 MHD_stop_daemon (d);
374 MHD_stop_daemon(d); 286 return 2048;
375 return 2048; 287 }
288 if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
289 {
290 curl_multi_remove_handle (multi, c);
291 curl_multi_cleanup (multi);
292 curl_easy_cleanup (c);
293 MHD_stop_daemon (d);
294 return 4096;
295 }
296 tv.tv_sec = 0;
297 tv.tv_usec = 1000;
298 select (max + 1, &rs, &ws, &es, &tv);
299 curl_multi_perform (multi, &running);
300 if (running == 0)
301 {
302 msg = curl_multi_info_read (multi, &running);
303 if (msg == NULL)
304 break;
305 if (msg->msg == CURLMSG_DONE)
306 {
307 if (msg->data.result != CURLE_OK)
308 printf ("%s failed at %s:%d: `%s'\n",
309 "curl_multi_perform",
310 __FILE__,
311 __LINE__, curl_easy_strerror (msg->data.result));
312 curl_multi_remove_handle (multi, c);
313 curl_multi_cleanup (multi);
314 curl_easy_cleanup (c);
315 c = NULL;
316 multi = NULL;
317 }
318 }
319 MHD_run (d);
376 } 320 }
377 if (MHD_YES != MHD_get_fdset(d, 321 if (multi != NULL)
378 &rs, 322 {
379 &ws, 323 curl_multi_remove_handle (multi, c);
380 &es, 324 curl_easy_cleanup (c);
381 &max)) { 325 curl_multi_cleanup (multi);
382 curl_multi_remove_handle(multi, c);
383 curl_multi_cleanup(multi);
384 curl_easy_cleanup(c);
385 MHD_stop_daemon(d);
386 return 4096;
387 } 326 }
388 tv.tv_sec = 0; 327 MHD_stop_daemon (d);
389 tv.tv_usec = 1000; 328 if (cbc.pos != strlen ("/hello_world"))
390 select(max + 1,
391 &rs,
392 &ws,
393 &es,
394 &tv);
395 curl_multi_perform(multi, &running);
396 if (running == 0) {
397 msg = curl_multi_info_read(multi,
398 &running);
399 if (msg == NULL)
400 break;
401 if (msg->msg == CURLMSG_DONE) {
402 if (msg->data.result != CURLE_OK)
403 printf("%s failed at %s:%d: `%s'\n",
404 "curl_multi_perform",
405 __FILE__,
406 __LINE__,
407 curl_easy_strerror(msg->data.result));
408 curl_multi_remove_handle(multi, c);
409 curl_multi_cleanup(multi);
410 curl_easy_cleanup(c);
411 c = NULL;
412 multi = NULL;
413 }
414 }
415 MHD_run(d);
416 }
417 if (multi != NULL) {
418 curl_multi_remove_handle(multi, c);
419 curl_easy_cleanup(c);
420 curl_multi_cleanup(multi);
421 }
422 MHD_stop_daemon(d);
423 if (cbc.pos != strlen("/hello_world"))
424 return 8192; 329 return 8192;
425 if (0 != strncmp("/hello_world", 330 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
426 cbc.buf,
427 strlen("/hello_world")))
428 return 16384; 331 return 16384;
429 return 0; 332 return 0;
430} 333}
431 334
432 335
433 336
434int main(int argc, 337int
435 char * const * argv) { 338main (int argc, char *const *argv)
339{
436 unsigned int errorCount = 0; 340 unsigned int errorCount = 0;
437 341
438 oneone = NULL != strstr(argv[0], "11"); 342 oneone = NULL != strstr (argv[0], "11");
439 if (0 != curl_global_init(CURL_GLOBAL_WIN32)) 343 if (0 != curl_global_init (CURL_GLOBAL_WIN32))
440 return 2; 344 return 2;
441 errorCount += testInternalPost(); 345 errorCount += testInternalPost ();
442 errorCount += testMultithreadedPost(); 346 errorCount += testMultithreadedPost ();
443 errorCount += testExternalPost(); 347 errorCount += testExternalPost ();
444 if (errorCount != 0) 348 if (errorCount != 0)
445 fprintf(stderr, 349 fprintf (stderr, "Error (code: %u)\n", errorCount);
446 "Error (code: %u)\n", 350 curl_global_cleanup ();
447 errorCount); 351 return errorCount != 0; /* 0 == pass */
448 curl_global_cleanup();
449 return errorCount != 0; /* 0 == pass */
450} 352}
diff --git a/src/daemon/daemontest_put.c b/src/daemon/daemontest_put.c
index e2f03bdf..342161c8 100644
--- a/src/daemon/daemontest_put.c
+++ b/src/daemon/daemontest_put.c
@@ -34,87 +34,82 @@
34 34
35static int oneone; 35static int oneone;
36 36
37struct CBC { 37struct CBC
38 char * buf; 38{
39 char *buf;
39 size_t pos; 40 size_t pos;
40 size_t size; 41 size_t size;
41}; 42};
42 43
43static size_t putBuffer(void * stream, 44static size_t
44 size_t size, 45putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
45 size_t nmemb, 46{
46 void * ptr) { 47 unsigned int *pos = ptr;
47 unsigned int * pos = ptr;
48 unsigned int wrt; 48 unsigned int wrt;
49 49
50 wrt = size * nmemb; 50 wrt = size * nmemb;
51 if (wrt > 8 - (*pos)) 51 if (wrt > 8 - (*pos))
52 wrt = 8 - (*pos); 52 wrt = 8 - (*pos);
53 memcpy(stream, 53 memcpy (stream, &("Hello123"[*pos]), wrt);
54 &("Hello123"[*pos]),
55 wrt);
56 (*pos) += wrt; 54 (*pos) += wrt;
57 return wrt; 55 return wrt;
58} 56}
59 57
60static size_t copyBuffer(void * ptr, 58static size_t
61 size_t size, 59copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
62 size_t nmemb, 60{
63 void * ctx) { 61 struct CBC *cbc = ctx;
64 struct CBC * cbc = ctx;
65 62
66 if (cbc->pos + size * nmemb > cbc->size) 63 if (cbc->pos + size * nmemb > cbc->size)
67 return 0; /* overflow */ 64 return 0; /* overflow */
68 memcpy(&cbc->buf[cbc->pos], 65 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
69 ptr,
70 size * nmemb);
71 cbc->pos += size * nmemb; 66 cbc->pos += size * nmemb;
72 return size * nmemb; 67 return size * nmemb;
73} 68}
74 69
75static int ahc_echo(void * cls, 70static int
76 struct MHD_Connection * connection, 71ahc_echo (void *cls,
77 const char * url, 72 struct MHD_Connection *connection,
78 const char * method, 73 const char *url,
79 const char * version, 74 const char *method,
80 const char * upload_data, 75 const char *version,
81 unsigned int * upload_data_size) { 76 const char *upload_data, unsigned int *upload_data_size)
82 int * done = cls; 77{
83 struct MHD_Response * response; 78 int *done = cls;
79 struct MHD_Response *response;
84 int ret; 80 int ret;
85 81
86 if (0 != strcmp("PUT", method)) 82 if (0 != strcmp ("PUT", method))
87 return MHD_NO; /* unexpected method */ 83 return MHD_NO; /* unexpected method */
88 if ((*done) == 0) { 84 if ((*done) == 0)
89 if (*upload_data_size != 8) 85 {
90 return MHD_YES; /* not yet ready */ 86 if (*upload_data_size != 8)
91 if (0 == memcmp(upload_data, 87 return MHD_YES; /* not yet ready */
92 "Hello123", 88 if (0 == memcmp (upload_data, "Hello123", 8))
93 8)) { 89 {
94 *upload_data_size = 0; 90 *upload_data_size = 0;
95 } else { 91 }
96 printf("Invalid upload data `%8s'!\n", 92 else
97 upload_data); 93 {
98 return MHD_NO; 94 printf ("Invalid upload data `%8s'!\n", upload_data);
95 return MHD_NO;
96 }
97 *done = 1;
98 return MHD_YES;
99 } 99 }
100 *done = 1; 100 response = MHD_create_response_from_data (strlen (url),
101 return MHD_YES; 101 (void *) url, MHD_NO, MHD_YES);
102 } 102 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
103 response = MHD_create_response_from_data(strlen(url), 103 MHD_destroy_response (response);
104 (void*) url,
105 MHD_NO,
106 MHD_YES);
107 ret = MHD_queue_response(connection,
108 MHD_HTTP_OK,
109 response);
110 MHD_destroy_response(response);
111 return ret; 104 return ret;
112} 105}
113 106
114 107
115static int testInternalPut() { 108static int
116 struct MHD_Daemon * d; 109testInternalPut ()
117 CURL * c; 110{
111 struct MHD_Daemon *d;
112 CURL *c;
118 char buf[2048]; 113 char buf[2048];
119 struct CBC cbc; 114 struct CBC cbc;
120 unsigned int pos = 0; 115 unsigned int pos = 0;
@@ -123,85 +118,58 @@ static int testInternalPut() {
123 cbc.buf = buf; 118 cbc.buf = buf;
124 cbc.size = 2048; 119 cbc.size = 2048;
125 cbc.pos = 0; 120 cbc.pos = 0;
126 d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, 121 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
127 1080, 122 1080,
128 NULL, 123 NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
129 NULL,
130 &ahc_echo,
131 &done_flag,
132 MHD_OPTION_END);
133 if (d == NULL) 124 if (d == NULL)
134 return 1; 125 return 1;
135 c = curl_easy_init(); 126 c = curl_easy_init ();
136 curl_easy_setopt(c, 127 curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world");
137 CURLOPT_URL, 128 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
138 "http://localhost:1080/hello_world"); 129 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
139 curl_easy_setopt(c, 130 curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
140 CURLOPT_WRITEFUNCTION, 131 curl_easy_setopt (c, CURLOPT_READDATA, &pos);
141 &copyBuffer); 132 curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
142 curl_easy_setopt(c, 133 curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
143 CURLOPT_WRITEDATA, 134 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
144 &cbc); 135 curl_easy_setopt (c, CURLOPT_TIMEOUT, 15L);
145 curl_easy_setopt(c,
146 CURLOPT_READFUNCTION,
147 &putBuffer);
148 curl_easy_setopt(c,
149 CURLOPT_READDATA,
150 &pos);
151 curl_easy_setopt(c,
152 CURLOPT_UPLOAD,
153 1L);
154 curl_easy_setopt(c,
155 CURLOPT_INFILESIZE_LARGE,
156 (curl_off_t) 8L);
157 curl_easy_setopt(c,
158 CURLOPT_FAILONERROR,
159 1);
160 curl_easy_setopt(c,
161 CURLOPT_TIMEOUT,
162 15L);
163 if (oneone) 136 if (oneone)
164 curl_easy_setopt(c, 137 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
165 CURLOPT_HTTP_VERSION,
166 CURL_HTTP_VERSION_1_1);
167 else 138 else
168 curl_easy_setopt(c, 139 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
169 CURLOPT_HTTP_VERSION, 140 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
170 CURL_HTTP_VERSION_1_0);
171 curl_easy_setopt(c,
172 CURLOPT_CONNECTTIMEOUT,
173 15L);
174 // NOTE: use of CONNECTTIMEOUT without also 141 // NOTE: use of CONNECTTIMEOUT without also
175 // setting NOSIGNAL results in really weird 142 // setting NOSIGNAL results in really weird
176 // crashes on my system! 143 // crashes on my system!
177 curl_easy_setopt(c, 144 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
178 CURLOPT_NOSIGNAL, 145 if (CURLE_OK != curl_easy_perform (c))
179 1); 146 {
180 if (CURLE_OK != curl_easy_perform(c)) { 147 curl_easy_cleanup (c);
181 curl_easy_cleanup(c); 148 MHD_stop_daemon (d);
182 MHD_stop_daemon(d); 149 return 2;
183 return 2; 150 }
184 } 151 curl_easy_cleanup (c);
185 curl_easy_cleanup(c); 152 if (cbc.pos != strlen ("/hello_world"))
186 if (cbc.pos != strlen("/hello_world")) { 153 {
187 MHD_stop_daemon(d); 154 MHD_stop_daemon (d);
188 return 4; 155 return 4;
189 } 156 }
190 157
191 if (0 != strncmp("/hello_world", 158 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
192 cbc.buf, 159 {
193 strlen("/hello_world"))) { 160 MHD_stop_daemon (d);
194 MHD_stop_daemon(d); 161 return 8;
195 return 8; 162 }
196 } 163 MHD_stop_daemon (d);
197 MHD_stop_daemon(d);
198 164
199 return 0; 165 return 0;
200} 166}
201 167
202static int testMultithreadedPut() { 168static int
203 struct MHD_Daemon * d; 169testMultithreadedPut ()
204 CURL * c; 170{
171 struct MHD_Daemon *d;
172 CURL *c;
205 char buf[2048]; 173 char buf[2048];
206 struct CBC cbc; 174 struct CBC cbc;
207 unsigned int pos = 0; 175 unsigned int pos = 0;
@@ -210,94 +178,68 @@ static int testMultithreadedPut() {
210 cbc.buf = buf; 178 cbc.buf = buf;
211 cbc.size = 2048; 179 cbc.size = 2048;
212 cbc.pos = 0; 180 cbc.pos = 0;
213 d = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG, 181 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
214 1081, 182 1081,
215 NULL, NULL, 183 NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
216 &ahc_echo,
217 &done_flag,
218 MHD_OPTION_END);
219 if (d == NULL) 184 if (d == NULL)
220 return 16; 185 return 16;
221 c = curl_easy_init(); 186 c = curl_easy_init ();
222 curl_easy_setopt(c, 187 curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
223 CURLOPT_URL, 188 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
224 "http://localhost:1081/hello_world"); 189 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
225 curl_easy_setopt(c, 190 curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
226 CURLOPT_WRITEFUNCTION, 191 curl_easy_setopt (c, CURLOPT_READDATA, &pos);
227 &copyBuffer); 192 curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
228 curl_easy_setopt(c, 193 curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
229 CURLOPT_WRITEDATA, 194 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
230 &cbc); 195 curl_easy_setopt (c, CURLOPT_TIMEOUT, 15L);
231 curl_easy_setopt(c,
232 CURLOPT_READFUNCTION,
233 &putBuffer);
234 curl_easy_setopt(c,
235 CURLOPT_READDATA,
236 &pos);
237 curl_easy_setopt(c,
238 CURLOPT_UPLOAD,
239 1L);
240 curl_easy_setopt(c,
241 CURLOPT_INFILESIZE_LARGE,
242 (curl_off_t) 8L);
243 curl_easy_setopt(c,
244 CURLOPT_FAILONERROR,
245 1);
246 curl_easy_setopt(c,
247 CURLOPT_TIMEOUT,
248 15L);
249 if (oneone) 196 if (oneone)
250 curl_easy_setopt(c, 197 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
251 CURLOPT_HTTP_VERSION,
252 CURL_HTTP_VERSION_1_1);
253 else 198 else
254 curl_easy_setopt(c, 199 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
255 CURLOPT_HTTP_VERSION, 200 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
256 CURL_HTTP_VERSION_1_0);
257 curl_easy_setopt(c,
258 CURLOPT_CONNECTTIMEOUT,
259 15L);
260 // NOTE: use of CONNECTTIMEOUT without also 201 // NOTE: use of CONNECTTIMEOUT without also
261 // setting NOSIGNAL results in really weird 202 // setting NOSIGNAL results in really weird
262 // crashes on my system! 203 // crashes on my system!
263 curl_easy_setopt(c, 204 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
264 CURLOPT_NOSIGNAL, 205 if (CURLE_OK != curl_easy_perform (c))
265 1); 206 {
266 if (CURLE_OK != curl_easy_perform(c)) { 207 curl_easy_cleanup (c);
267 curl_easy_cleanup(c); 208 MHD_stop_daemon (d);
268 MHD_stop_daemon(d); 209 return 32;
269 return 32; 210 }
270 } 211 curl_easy_cleanup (c);
271 curl_easy_cleanup(c); 212 if (cbc.pos != strlen ("/hello_world"))
272 if (cbc.pos != strlen("/hello_world")) { 213 {
273 MHD_stop_daemon(d); 214 MHD_stop_daemon (d);
274 return 64; 215 return 64;
275 } 216 }
276 if (0 != strncmp("/hello_world", 217 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
277 cbc.buf, 218 {
278 strlen("/hello_world"))) { 219 MHD_stop_daemon (d);
279 MHD_stop_daemon(d); 220 return 128;
280 return 128; 221 }
281 } 222 MHD_stop_daemon (d);
282 MHD_stop_daemon(d);
283 223
284 return 0; 224 return 0;
285} 225}
286 226
287 227
288static int testExternalPut() { 228static int
289 struct MHD_Daemon * d; 229testExternalPut ()
290 CURL * c; 230{
231 struct MHD_Daemon *d;
232 CURL *c;
291 char buf[2048]; 233 char buf[2048];
292 struct CBC cbc; 234 struct CBC cbc;
293 CURLM * multi; 235 CURLM *multi;
294 CURLMcode mret; 236 CURLMcode mret;
295 fd_set rs; 237 fd_set rs;
296 fd_set ws; 238 fd_set ws;
297 fd_set es; 239 fd_set es;
298 int max; 240 int max;
299 int running; 241 int running;
300 struct CURLMsg * msg; 242 struct CURLMsg *msg;
301 time_t start; 243 time_t start;
302 struct timeval tv; 244 struct timeval tv;
303 unsigned int pos = 0; 245 unsigned int pos = 0;
@@ -307,166 +249,126 @@ static int testExternalPut() {
307 cbc.buf = buf; 249 cbc.buf = buf;
308 cbc.size = 2048; 250 cbc.size = 2048;
309 cbc.pos = 0; 251 cbc.pos = 0;
310 d = MHD_start_daemon(MHD_USE_DEBUG, 252 d = MHD_start_daemon (MHD_USE_DEBUG,
311 1082, 253 1082,
312 NULL, 254 NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
313 NULL,
314 &ahc_echo,
315 &done_flag,
316 MHD_OPTION_END);
317 if (d == NULL) 255 if (d == NULL)
318 return 256; 256 return 256;
319 c = curl_easy_init(); 257 c = curl_easy_init ();
320 curl_easy_setopt(c, 258 curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world");
321 CURLOPT_URL, 259 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
322 "http://localhost:1082/hello_world"); 260 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
323 curl_easy_setopt(c, 261 curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
324 CURLOPT_WRITEFUNCTION, 262 curl_easy_setopt (c, CURLOPT_READDATA, &pos);
325 &copyBuffer); 263 curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
326 curl_easy_setopt(c, 264 curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
327 CURLOPT_WRITEDATA, 265 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
328 &cbc); 266 curl_easy_setopt (c, CURLOPT_TIMEOUT, 15L);
329 curl_easy_setopt(c,
330 CURLOPT_READFUNCTION,
331 &putBuffer);
332 curl_easy_setopt(c,
333 CURLOPT_READDATA,
334 &pos);
335 curl_easy_setopt(c,
336 CURLOPT_UPLOAD,
337 1L);
338 curl_easy_setopt(c,
339 CURLOPT_INFILESIZE_LARGE,
340 (curl_off_t) 8L);
341 curl_easy_setopt(c,
342 CURLOPT_FAILONERROR,
343 1);
344 curl_easy_setopt(c,
345 CURLOPT_TIMEOUT,
346 15L);
347 if (oneone) 267 if (oneone)
348 curl_easy_setopt(c, 268 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
349 CURLOPT_HTTP_VERSION,
350 CURL_HTTP_VERSION_1_1);
351 else 269 else
352 curl_easy_setopt(c, 270 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
353 CURLOPT_HTTP_VERSION, 271 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
354 CURL_HTTP_VERSION_1_0);
355 curl_easy_setopt(c,
356 CURLOPT_CONNECTTIMEOUT,
357 15L);
358 // NOTE: use of CONNECTTIMEOUT without also 272 // NOTE: use of CONNECTTIMEOUT without also
359 // setting NOSIGNAL results in really weird 273 // setting NOSIGNAL results in really weird
360 // crashes on my system! 274 // crashes on my system!
361 curl_easy_setopt(c, 275 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
362 CURLOPT_NOSIGNAL,
363 1);
364 276
365 277
366 multi = curl_multi_init(); 278 multi = curl_multi_init ();
367 if (multi == NULL) { 279 if (multi == NULL)
368 curl_easy_cleanup(c); 280 {
369 MHD_stop_daemon(d); 281 curl_easy_cleanup (c);
370 return 512; 282 MHD_stop_daemon (d);
371 } 283 return 512;
372 mret = curl_multi_add_handle(multi, c); 284 }
373 if (mret != CURLM_OK) { 285 mret = curl_multi_add_handle (multi, c);
374 curl_multi_cleanup(multi); 286 if (mret != CURLM_OK)
375 curl_easy_cleanup(c); 287 {
376 MHD_stop_daemon(d); 288 curl_multi_cleanup (multi);
377 return 1024; 289 curl_easy_cleanup (c);
378 } 290 MHD_stop_daemon (d);
379 start = time(NULL); 291 return 1024;
380 while ( (time(NULL) - start < 5) && 292 }
381 (multi != NULL) ) { 293 start = time (NULL);
382 max = 0; 294 while ((time (NULL) - start < 5) && (multi != NULL))
383 FD_ZERO(&rs); 295 {
384 FD_ZERO(&ws); 296 max = 0;
385 FD_ZERO(&es); 297 FD_ZERO (&rs);
386 curl_multi_perform(multi, &running); 298 FD_ZERO (&ws);
387 mret = curl_multi_fdset(multi, 299 FD_ZERO (&es);
388 &rs, 300 curl_multi_perform (multi, &running);
389 &ws, 301 mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
390 &es, 302 if (mret != CURLM_OK)
391 &max); 303 {
392 if (mret != CURLM_OK) { 304 curl_multi_remove_handle (multi, c);
393 curl_multi_remove_handle(multi, c); 305 curl_multi_cleanup (multi);
394 curl_multi_cleanup(multi); 306 curl_easy_cleanup (c);
395 curl_easy_cleanup(c); 307 MHD_stop_daemon (d);
396 MHD_stop_daemon(d); 308 return 2048;
397 return 2048; 309 }
310 if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
311 {
312 curl_multi_remove_handle (multi, c);
313 curl_multi_cleanup (multi);
314 curl_easy_cleanup (c);
315 MHD_stop_daemon (d);
316 return 4096;
317 }
318 tv.tv_sec = 0;
319 tv.tv_usec = 1000;
320 select (max + 1, &rs, &ws, &es, &tv);
321 curl_multi_perform (multi, &running);
322 if (running == 0)
323 {
324 msg = curl_multi_info_read (multi, &running);
325 if (msg == NULL)
326 break;
327 if (msg->msg == CURLMSG_DONE)
328 {
329 if (msg->data.result != CURLE_OK)
330 printf ("%s failed at %s:%d: `%s'\n",
331 "curl_multi_perform",
332 __FILE__,
333 __LINE__, curl_easy_strerror (msg->data.result));
334 curl_multi_remove_handle (multi, c);
335 curl_multi_cleanup (multi);
336 curl_easy_cleanup (c);
337 c = NULL;
338 multi = NULL;
339 }
340 }
341 MHD_run (d);
398 } 342 }
399 if (MHD_YES != MHD_get_fdset(d, 343 if (multi != NULL)
400 &rs, 344 {
401 &ws, 345 curl_multi_remove_handle (multi, c);
402 &es, 346 curl_easy_cleanup (c);
403 &max)) { 347 curl_multi_cleanup (multi);
404 curl_multi_remove_handle(multi, c);
405 curl_multi_cleanup(multi);
406 curl_easy_cleanup(c);
407 MHD_stop_daemon(d);
408 return 4096;
409 } 348 }
410 tv.tv_sec = 0; 349 MHD_stop_daemon (d);
411 tv.tv_usec = 1000; 350 if (cbc.pos != strlen ("/hello_world"))
412 select(max + 1,
413 &rs,
414 &ws,
415 &es,
416 &tv);
417 curl_multi_perform(multi, &running);
418 if (running == 0) {
419 msg = curl_multi_info_read(multi,
420 &running);
421 if (msg == NULL)
422 break;
423 if (msg->msg == CURLMSG_DONE) {
424 if (msg->data.result != CURLE_OK)
425 printf("%s failed at %s:%d: `%s'\n",
426 "curl_multi_perform",
427 __FILE__,
428 __LINE__,
429 curl_easy_strerror(msg->data.result));
430 curl_multi_remove_handle(multi, c);
431 curl_multi_cleanup(multi);
432 curl_easy_cleanup(c);
433 c = NULL;
434 multi = NULL;
435 }
436 }
437 MHD_run(d);
438 }
439 if (multi != NULL) {
440 curl_multi_remove_handle(multi, c);
441 curl_easy_cleanup(c);
442 curl_multi_cleanup(multi);
443 }
444 MHD_stop_daemon(d);
445 if (cbc.pos != strlen("/hello_world"))
446 return 8192; 351 return 8192;
447 if (0 != strncmp("/hello_world", 352 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
448 cbc.buf,
449 strlen("/hello_world")))
450 return 16384; 353 return 16384;
451 return 0; 354 return 0;
452} 355}
453 356
454 357
455 358
456int main(int argc, 359int
457 char * const * argv) { 360main (int argc, char *const *argv)
361{
458 unsigned int errorCount = 0; 362 unsigned int errorCount = 0;
459 363
460 oneone = NULL != strstr(argv[0], "11"); 364 oneone = NULL != strstr (argv[0], "11");
461 if (0 != curl_global_init(CURL_GLOBAL_WIN32)) 365 if (0 != curl_global_init (CURL_GLOBAL_WIN32))
462 return 2; 366 return 2;
463 errorCount += testInternalPut(); 367 errorCount += testInternalPut ();
464 errorCount += testMultithreadedPut(); 368 errorCount += testMultithreadedPut ();
465 errorCount += testExternalPut(); 369 errorCount += testExternalPut ();
466 if (errorCount != 0) 370 if (errorCount != 0)
467 fprintf(stderr, 371 fprintf (stderr, "Error (code: %u)\n", errorCount);
468 "Error (code: %u)\n", 372 curl_global_cleanup ();
469 errorCount); 373 return errorCount != 0; /* 0 == pass */
470 curl_global_cleanup();
471 return errorCount != 0; /* 0 == pass */
472} 374}
diff --git a/src/daemon/fileserver_example.c b/src/daemon/fileserver_example.c
index 989ab7d5..6f39f491 100644
--- a/src/daemon/fileserver_example.c
+++ b/src/daemon/fileserver_example.c
@@ -37,78 +37,69 @@
37 37
38#define PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>" 38#define PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"
39 39
40static int file_reader(void * cls, 40static int
41 size_t pos, 41file_reader (void *cls, size_t pos, char *buf, int max)
42 char * buf, 42{
43 int max) { 43 FILE *file = cls;
44 FILE * file = cls;
45 44
46 fseek(file, pos, SEEK_SET); 45 fseek (file, pos, SEEK_SET);
47 return fread(buf, 46 return fread (buf, 1, max, file);
48 1,
49 max,
50 file);
51} 47}
52 48
53static int ahc_echo(void * cls, 49static int
54 struct MHD_Connection * connection, 50ahc_echo (void *cls,
55 const char * url, 51 struct MHD_Connection *connection,
56 const char * method, 52 const char *url,
57 const char * upload_data, 53 const char *method,
58 const char * version, 54 const char *upload_data,
59 unsigned int * upload_data_size) { 55 const char *version, unsigned int *upload_data_size)
60 struct MHD_Response * response; 56{
57 struct MHD_Response *response;
61 int ret; 58 int ret;
62 FILE * file; 59 FILE *file;
63 struct stat buf; 60 struct stat buf;
64 61
65 if (0 != strcmp(method, "GET")) 62 if (0 != strcmp (method, "GET"))
66 return MHD_NO; /* unexpected method */ 63 return MHD_NO; /* unexpected method */
67 file = fopen(&url[1], "r"); 64 file = fopen (&url[1], "r");
68 if (file == NULL) { 65 if (file == NULL)
69 response = MHD_create_response_from_data(strlen(PAGE), 66 {
70 (void*) PAGE, 67 response = MHD_create_response_from_data (strlen (PAGE),
71 MHD_NO, 68 (void *) PAGE,
72 MHD_NO); 69 MHD_NO, MHD_NO);
73 ret = MHD_queue_response(connection, 70 ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
74 MHD_HTTP_NOT_FOUND, 71 MHD_destroy_response (response);
75 response); 72 }
76 MHD_destroy_response(response); 73 else
77 } else { 74 {
78 stat(&url[1], 75 stat (&url[1], &buf);
79 &buf); 76 response = MHD_create_response_from_callback (buf.st_size,
80 response = MHD_create_response_from_callback(buf.st_size, 77 &file_reader,
81 &file_reader, 78 file,
82 file, 79 (MHD_ContentReaderFreeCallback)
83 (MHD_ContentReaderFreeCallback) &fclose); 80 & fclose);
84 ret = MHD_queue_response(connection, 81 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
85 MHD_HTTP_OK, 82 MHD_destroy_response (response);
86 response); 83 }
87 MHD_destroy_response(response);
88 }
89 return ret; 84 return ret;
90} 85}
91 86
92int main(int argc, 87int
93 char * const * argv) { 88main (int argc, char *const *argv)
94 struct MHD_Daemon * d; 89{
90 struct MHD_Daemon *d;
95 91
96 if (argc != 3) { 92 if (argc != 3)
97 printf("%s PORT SECONDS-TO-RUN\n", 93 {
98 argv[0]); 94 printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
99 return 1; 95 return 1;
100 } 96 }
101 d = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG, 97 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
102 atoi(argv[1]), 98 atoi (argv[1]),
103 NULL, 99 NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
104 NULL,
105 &ahc_echo,
106 PAGE,
107 MHD_OPTION_END);
108 if (d == NULL) 100 if (d == NULL)
109 return 1; 101 return 1;
110 sleep(atoi(argv[2])); 102 sleep (atoi (argv[2]));
111 MHD_stop_daemon(d); 103 MHD_stop_daemon (d);
112 return 0; 104 return 0;
113} 105}
114
diff --git a/src/daemon/internal.c b/src/daemon/internal.c
index ef67affc..6f674470 100644
--- a/src/daemon/internal.c
+++ b/src/daemon/internal.c
@@ -32,15 +32,14 @@
32 * fprintf-like helper function for logging debug 32 * fprintf-like helper function for logging debug
33 * messages. 33 * messages.
34 */ 34 */
35void MHD_DLOG(const struct MHD_Daemon * daemon, 35void
36 const char * format, 36MHD_DLOG (const struct MHD_Daemon *daemon, const char *format, ...)
37 ...) { 37{
38 va_list va; 38 va_list va;
39 39
40 if ( (daemon->options & MHD_USE_DEBUG) == 0) 40 if ((daemon->options & MHD_USE_DEBUG) == 0)
41 return; 41 return;
42 va_start(va, format); 42 va_start (va, format);
43 VFPRINTF(stderr, format, va); 43 VFPRINTF (stderr, format, va);
44 va_end(va); 44 va_end (va);
45} 45}
46
diff --git a/src/daemon/internal.h b/src/daemon/internal.h
index 8aa08243..8bc33c29 100644
--- a/src/daemon/internal.h
+++ b/src/daemon/internal.h
@@ -62,59 +62,60 @@
62 * fprintf-like helper function for logging debug 62 * fprintf-like helper function for logging debug
63 * messages. 63 * messages.
64 */ 64 */
65void MHD_DLOG(const struct MHD_Daemon * daemon, 65void MHD_DLOG (const struct MHD_Daemon *daemon, const char *format, ...);
66 const char * format,
67 ...);
68 66
69 67
70/** 68/**
71 * Header or cookie in HTTP request or response. 69 * Header or cookie in HTTP request or response.
72 */ 70 */
73struct MHD_HTTP_Header { 71struct MHD_HTTP_Header
74 struct MHD_HTTP_Header * next; 72{
73 struct MHD_HTTP_Header *next;
75 74
76 char * header; 75 char *header;
77 76
78 char * value; 77 char *value;
79 78
80 enum MHD_ValueKind kind; 79 enum MHD_ValueKind kind;
81}; 80};
82 81
83 82
84struct MHD_Access_Handler { 83struct MHD_Access_Handler
85 struct MHD_Access_Handler * next; 84{
85 struct MHD_Access_Handler *next;
86 86
87 char * uri_prefix; 87 char *uri_prefix;
88 88
89 MHD_AccessHandlerCallback dh; 89 MHD_AccessHandlerCallback dh;
90 90
91 void * dh_cls; 91 void *dh_cls;
92}; 92};
93 93
94 94
95/** 95/**
96 * Representation of a response. 96 * Representation of a response.
97 */ 97 */
98struct MHD_Response { 98struct MHD_Response
99{
99 100
100 /** 101 /**
101 * Headers to send for the response. Initially 102 * Headers to send for the response. Initially
102 * the linked list is created in inverse order; 103 * the linked list is created in inverse order;
103 * the order should be inverted before sending! 104 * the order should be inverted before sending!
104 */ 105 */
105 struct MHD_HTTP_Header * first_header; 106 struct MHD_HTTP_Header *first_header;
106 107
107 /** 108 /**
108 * Buffer pointing to data that we are supposed 109 * Buffer pointing to data that we are supposed
109 * to send as a response. 110 * to send as a response.
110 */ 111 */
111 char * data; 112 char *data;
112 113
113 /** 114 /**
114 * Closure to give to the content reader 115 * Closure to give to the content reader
115 * free callback. 116 * free callback.
116 */ 117 */
117 void * crc_cls; 118 void *crc_cls;
118 119
119 /** 120 /**
120 * How do we get more data? NULL if we are 121 * How do we get more data? NULL if we are
@@ -165,27 +166,28 @@ struct MHD_Response {
165 166
166 167
167 168
168struct MHD_Connection { 169struct MHD_Connection
170{
169 171
170 /** 172 /**
171 * This is a linked list. 173 * This is a linked list.
172 */ 174 */
173 struct MHD_Connection * next; 175 struct MHD_Connection *next;
174 176
175 /** 177 /**
176 * Reference to the MHD_Daemon struct. 178 * Reference to the MHD_Daemon struct.
177 */ 179 */
178 struct MHD_Daemon * daemon; 180 struct MHD_Daemon *daemon;
179 181
180 /** 182 /**
181 * Linked list of parsed headers. 183 * Linked list of parsed headers.
182 */ 184 */
183 struct MHD_HTTP_Header * headers_received; 185 struct MHD_HTTP_Header *headers_received;
184 186
185 /** 187 /**
186 * Response to transmit (initially NULL). 188 * Response to transmit (initially NULL).
187 */ 189 */
188 struct MHD_Response * response; 190 struct MHD_Response *response;
189 191
190 /** 192 /**
191 * The memory pool is created whenever we first read 193 * The memory pool is created whenever we first read
@@ -197,43 +199,43 @@ struct MHD_Connection {
197 * connections) and the IP address (which persists 199 * connections) and the IP address (which persists
198 * across individual requests). 200 * across individual requests).
199 */ 201 */
200 struct MemoryPool * pool; 202 struct MemoryPool *pool;
201 203
202 /** 204 /**
203 * Request method. Should be GET/POST/etc. Allocated 205 * Request method. Should be GET/POST/etc. Allocated
204 * in pool. 206 * in pool.
205 */ 207 */
206 char * method; 208 char *method;
207 209
208 /** 210 /**
209 * Requested URL (everything after "GET" only). Allocated 211 * Requested URL (everything after "GET" only). Allocated
210 * in pool. 212 * in pool.
211 */ 213 */
212 char * url; 214 char *url;
213 215
214 /** 216 /**
215 * HTTP version string (i.e. http/1.1). Allocated 217 * HTTP version string (i.e. http/1.1). Allocated
216 * in pool. 218 * in pool.
217 */ 219 */
218 char * version; 220 char *version;
219 221
220 /** 222 /**
221 * Buffer for reading requests. Allocated 223 * Buffer for reading requests. Allocated
222 * in pool. 224 * in pool.
223 */ 225 */
224 char * read_buffer; 226 char *read_buffer;
225 227
226 /** 228 /**
227 * Buffer for writing response (headers only). Allocated 229 * Buffer for writing response (headers only). Allocated
228 * in pool. 230 * in pool.
229 */ 231 */
230 char * write_buffer; 232 char *write_buffer;
231 233
232 /** 234 /**
233 * Foreign address (of length addr_len). MALLOCED (not 235 * Foreign address (of length addr_len). MALLOCED (not
234 * in pool!). 236 * in pool!).
235 */ 237 */
236 struct sockaddr_in * addr; 238 struct sockaddr_in *addr;
237 239
238 /** 240 /**
239 * Thread for this connection (if we are using 241 * Thread for this connection (if we are using
@@ -342,20 +344,21 @@ struct MHD_Connection {
342 344
343 345
344 346
345struct MHD_Daemon { 347struct MHD_Daemon
348{
346 349
347 struct MHD_Access_Handler * handlers; 350 struct MHD_Access_Handler *handlers;
348 351
349 struct MHD_Access_Handler default_handler; 352 struct MHD_Access_Handler default_handler;
350 353
351 /** 354 /**
352 * Linked list of our current connections. 355 * Linked list of our current connections.
353 */ 356 */
354 struct MHD_Connection * connections; 357 struct MHD_Connection *connections;
355 358
356 MHD_AcceptPolicyCallback apc; 359 MHD_AcceptPolicyCallback apc;
357 360
358 void * apc_cls; 361 void *apc_cls;
359 362
360 /** 363 /**
361 * PID of the select thread (if we have internal select) 364 * PID of the select thread (if we have internal select)
@@ -390,7 +393,7 @@ struct MHD_Daemon {
390 /** 393 /**
391 * Listen port. 394 * Listen port.
392 */ 395 */
393 unsigned short port; 396 unsigned short port;
394 397
395}; 398};
396 399
diff --git a/src/daemon/memorypool.c b/src/daemon/memorypool.c
index d8e835e8..37cc50c1 100644
--- a/src/daemon/memorypool.c
+++ b/src/daemon/memorypool.c
@@ -26,12 +26,13 @@
26 26
27#include "memorypool.h" 27#include "memorypool.h"
28 28
29struct MemoryPool { 29struct MemoryPool
30{
30 31
31 /** 32 /**
32 * Pointer to the pool's memory 33 * Pointer to the pool's memory
33 */ 34 */
34 char * memory; 35 char *memory;
35 36
36 /** 37 /**
37 * Size of the pool. 38 * Size of the pool.
@@ -59,25 +60,30 @@ struct MemoryPool {
59 * 60 *
60 * @param max maximum size of the pool 61 * @param max maximum size of the pool
61 */ 62 */
62struct MemoryPool * MHD_pool_create(unsigned int max) { 63struct MemoryPool *
63 struct MemoryPool * pool; 64MHD_pool_create (unsigned int max)
65{
66 struct MemoryPool *pool;
64 67
65 pool = malloc(sizeof(struct MemoryPool)); 68 pool = malloc (sizeof (struct MemoryPool));
66 if (pool == NULL) 69 if (pool == NULL)
67 return NULL; 70 return NULL;
68 pool->memory = MMAP(NULL, max, PROT_READ | PROT_WRITE, 71 pool->memory = MMAP (NULL, max, PROT_READ | PROT_WRITE,
69 MAP_ANONYMOUS, -1, 0); 72 MAP_ANONYMOUS, -1, 0);
70 if ( (pool->memory == MAP_FAILED) || 73 if ((pool->memory == MAP_FAILED) || (pool->memory == NULL))
71 (pool->memory == NULL) ) { 74 {
72 pool->memory = malloc(max); 75 pool->memory = malloc (max);
73 if (pool->memory == NULL) { 76 if (pool->memory == NULL)
74 free(pool); 77 {
75 return NULL; 78 free (pool);
79 return NULL;
80 }
81 pool->is_mmap = 0;
82 }
83 else
84 {
85 pool->is_mmap = 1;
76 } 86 }
77 pool->is_mmap = 0;
78 } else {
79 pool->is_mmap = 1;
80 }
81 pool->pos = 0; 87 pool->pos = 0;
82 pool->end = max; 88 pool->end = max;
83 pool->size = max; 89 pool->size = max;
@@ -87,14 +93,16 @@ struct MemoryPool * MHD_pool_create(unsigned int max) {
87/** 93/**
88 * Destroy a memory pool. 94 * Destroy a memory pool.
89 */ 95 */
90void MHD_pool_destroy(struct MemoryPool * pool) { 96void
97MHD_pool_destroy (struct MemoryPool *pool)
98{
91 if (pool == NULL) 99 if (pool == NULL)
92 return; 100 return;
93 if (pool->is_mmap == 0) 101 if (pool->is_mmap == 0)
94 free(pool->memory); 102 free (pool->memory);
95 else 103 else
96 MUNMAP(pool->memory, pool->size); 104 MUNMAP (pool->memory, pool->size);
97 free(pool); 105 free (pool);
98} 106}
99 107
100/** 108/**
@@ -102,21 +110,23 @@ void MHD_pool_destroy(struct MemoryPool * pool) {
102 * @return NULL if the pool cannot support size more 110 * @return NULL if the pool cannot support size more
103 * bytes 111 * bytes
104 */ 112 */
105void * MHD_pool_allocate(struct MemoryPool * pool, 113void *
106 unsigned int size, 114MHD_pool_allocate (struct MemoryPool *pool, unsigned int size, int from_end)
107 int from_end) { 115{
108 void * ret; 116 void *ret;
109 117
110 if ( (pool->pos + size > pool->end) || 118 if ((pool->pos + size > pool->end) || (pool->pos + size < pool->pos))
111 (pool->pos + size < pool->pos) )
112 return NULL; 119 return NULL;
113 if (from_end == MHD_YES) { 120 if (from_end == MHD_YES)
114 ret = &pool->memory[pool->end - size]; 121 {
115 pool->end -= size; 122 ret = &pool->memory[pool->end - size];
116 } else { 123 pool->end -= size;
117 ret = &pool->memory[pool->pos]; 124 }
118 pool->pos += size; 125 else
119 } 126 {
127 ret = &pool->memory[pool->pos];
128 pool->pos += size;
129 }
120 return ret; 130 return ret;
121} 131}
122 132
@@ -136,43 +146,40 @@ void * MHD_pool_allocate(struct MemoryPool * pool,
136 * NULL if the pool cannot support new_size 146 * NULL if the pool cannot support new_size
137 * bytes (old continues to be valid for old_size) 147 * bytes (old continues to be valid for old_size)
138 */ 148 */
139void * MHD_pool_reallocate(struct MemoryPool * pool, 149void *
140 void * old, 150MHD_pool_reallocate (struct MemoryPool *pool,
141 unsigned int old_size, 151 void *old, unsigned int old_size, unsigned int new_size)
142 unsigned int new_size) { 152{
143 void * ret; 153 void *ret;
144 154
145 if ( (pool->end < old_size) || 155 if ((pool->end < old_size) || (pool->end < new_size))
146 (pool->end < new_size) ) 156 return NULL; /* unsatisfiable or bogus request */
147 return NULL; /* unsatisfiable or bogus request */ 157
148 158 if ((pool->pos >= old_size) && (&pool->memory[pool->pos - old_size] == old))
149 if ( (pool->pos >= old_size) && 159 {
150 (&pool->memory[pool->pos - old_size] == old) ) { 160 /* was the previous allocation - optimize! */
151 /* was the previous allocation - optimize! */ 161 if (pool->pos + new_size - old_size <= pool->end)
152 if (pool->pos + new_size - old_size <= pool->end) { 162 {
153 /* fits */ 163 /* fits */
154 pool->pos += new_size - old_size; 164 pool->pos += new_size - old_size;
155 if (new_size < old_size) /* shrinking - zero again! */ 165 if (new_size < old_size) /* shrinking - zero again! */
156 memset(&pool->memory[pool->pos], 166 memset (&pool->memory[pool->pos], 0, old_size - new_size);
157 0, 167 return old;
158 old_size - new_size); 168 }
159 return old; 169 /* does not fit */
170 return NULL;
160 } 171 }
161 /* does not fit */
162 return NULL;
163 }
164 if (new_size <= old_size) 172 if (new_size <= old_size)
165 return old; /* cannot shrink, no need to move */ 173 return old; /* cannot shrink, no need to move */
166 if ( (pool->pos + new_size >= pool->pos) && 174 if ((pool->pos + new_size >= pool->pos) &&
167 (pool->pos + new_size <= pool->end) ) { 175 (pool->pos + new_size <= pool->end))
168 /* fits */ 176 {
169 ret = &pool->memory[pool->pos]; 177 /* fits */
170 memcpy(ret, 178 ret = &pool->memory[pool->pos];
171 old, 179 memcpy (ret, old, old_size);
172 old_size); 180 pool->pos += new_size;
173 pool->pos += new_size; 181 return ret;
174 return ret; 182 }
175 }
176 /* does not fit */ 183 /* does not fit */
177 return NULL; 184 return NULL;
178} 185}
diff --git a/src/daemon/memorypool.h b/src/daemon/memorypool.h
index 693b03f6..92e09a51 100644
--- a/src/daemon/memorypool.h
+++ b/src/daemon/memorypool.h
@@ -43,12 +43,12 @@ struct MemoryPool;
43 * 43 *
44 * @param max maximum size of the pool 44 * @param max maximum size of the pool
45 */ 45 */
46struct MemoryPool * MHD_pool_create(unsigned int max); 46struct MemoryPool *MHD_pool_create (unsigned int max);
47 47
48/** 48/**
49 * Destroy a memory pool. 49 * Destroy a memory pool.
50 */ 50 */
51void MHD_pool_destroy(struct MemoryPool * pool); 51void MHD_pool_destroy (struct MemoryPool *pool);
52 52
53/** 53/**
54 * Allocate size bytes from the pool. 54 * Allocate size bytes from the pool.
@@ -59,9 +59,8 @@ void MHD_pool_destroy(struct MemoryPool * pool);
59 * @return NULL if the pool cannot support size more 59 * @return NULL if the pool cannot support size more
60 * bytes 60 * bytes
61 */ 61 */
62void * MHD_pool_allocate(struct MemoryPool * pool, 62void *MHD_pool_allocate (struct MemoryPool *pool,
63 unsigned int size, 63 unsigned int size, int from_end);
64 int from_end);
65 64
66/** 65/**
67 * Reallocate a block of memory obtained from the pool. 66 * Reallocate a block of memory obtained from the pool.
@@ -79,9 +78,8 @@ void * MHD_pool_allocate(struct MemoryPool * pool,
79 * NULL if the pool cannot support new_size 78 * NULL if the pool cannot support new_size
80 * bytes (old continues to be valid for old_size) 79 * bytes (old continues to be valid for old_size)
81 */ 80 */
82void * MHD_pool_reallocate(struct MemoryPool * pool, 81void *MHD_pool_reallocate (struct MemoryPool *pool,
83 void * old, 82 void *old,
84 unsigned int old_size, 83 unsigned int old_size, unsigned int new_size);
85 unsigned int new_size);
86 84
87#endif 85#endif
diff --git a/src/daemon/minimal_example.c b/src/daemon/minimal_example.c
index 10b54aac..8de0064e 100644
--- a/src/daemon/minimal_example.c
+++ b/src/daemon/minimal_example.c
@@ -35,50 +35,43 @@
35 35
36#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>" 36#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
37 37
38static int ahc_echo(void * cls, 38static int
39 struct MHD_Connection * connection, 39ahc_echo (void *cls,
40 const char * url, 40 struct MHD_Connection *connection,
41 const char * method, 41 const char *url,
42 const char * upload_data, 42 const char *method,
43 const char * version, 43 const char *upload_data,
44 unsigned int * upload_data_size) { 44 const char *version, unsigned int *upload_data_size)
45 const char * me = cls; 45{
46 struct MHD_Response * response; 46 const char *me = cls;
47 struct MHD_Response *response;
47 int ret; 48 int ret;
48 49
49 if (0 != strcmp(method, "GET")) 50 if (0 != strcmp (method, "GET"))
50 return MHD_NO; /* unexpected method */ 51 return MHD_NO; /* unexpected method */
51 response = MHD_create_response_from_data(strlen(me), 52 response = MHD_create_response_from_data (strlen (me),
52 (void*) me, 53 (void *) me, MHD_NO, MHD_NO);
53 MHD_NO, 54 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
54 MHD_NO); 55 MHD_destroy_response (response);
55 ret = MHD_queue_response(connection,
56 MHD_HTTP_OK,
57 response);
58 MHD_destroy_response(response);
59 return ret; 56 return ret;
60} 57}
61 58
62int main(int argc, 59int
63 char * const * argv) { 60main (int argc, char *const *argv)
64 struct MHD_Daemon * d; 61{
62 struct MHD_Daemon *d;
65 63
66 if (argc != 3) { 64 if (argc != 3)
67 printf("%s PORT SECONDS-TO-RUN\n", 65 {
68 argv[0]); 66 printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
69 return 1; 67 return 1;
70 } 68 }
71 d = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG, 69 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
72 atoi(argv[1]), 70 atoi (argv[1]),
73 NULL, 71 NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
74 NULL,
75 &ahc_echo,
76 PAGE,
77 MHD_OPTION_END);
78 if (d == NULL) 72 if (d == NULL)
79 return 1; 73 return 1;
80 sleep(atoi(argv[2])); 74 sleep (atoi (argv[2]));
81 MHD_stop_daemon(d); 75 MHD_stop_daemon (d);
82 return 0; 76 return 0;
83} 77}
84
diff --git a/src/daemon/plibc.h b/src/daemon/plibc.h
index 65c431d5..4af3552d 100644
--- a/src/daemon/plibc.h
+++ b/src/daemon/plibc.h
@@ -29,21 +29,22 @@
29#define _PLIBC_H_ 29#define _PLIBC_H_
30 30
31#ifndef SIGALRM 31#ifndef SIGALRM
32 #define SIGALRM 14 32#define SIGALRM 14
33#endif 33#endif
34 34
35#ifdef __cplusplus 35#ifdef __cplusplus
36extern "C" { 36extern "C"
37{
37#endif 38#endif
38 39
39#ifdef Q_OS_WIN32 40#ifdef Q_OS_WIN32
40 #define WINDOWS 1 41#define WINDOWS 1
41#endif 42#endif
42 43
43#ifdef WINDOWS 44#ifdef WINDOWS
44 45
45#if ENABLE_NLS 46#if ENABLE_NLS
46 #include "langinfo.h" 47#include "langinfo.h"
47#endif 48#endif
48 49
49#include <windows.h> 50#include <windows.h>
@@ -75,8 +76,8 @@ extern "C" {
75#define int64_t long long 76#define int64_t long long
76#define int32_t long 77#define int32_t long
77 78
78struct stat64 79 struct stat64
79{ 80 {
80 _dev_t st_dev; 81 _dev_t st_dev;
81 _ino_t st_ino; 82 _ino_t st_ino;
82 _mode_t st_mode; 83 _mode_t st_mode;
@@ -88,112 +89,112 @@ struct stat64
88 __time64_t st_atime; 89 __time64_t st_atime;
89 __time64_t st_mtime; 90 __time64_t st_mtime;
90 __time64_t st_ctime; 91 __time64_t st_ctime;
91}; 92 };
92 93
93#ifndef pid_t 94#ifndef pid_t
94 #define pid_t int 95#define pid_t int
95#endif 96#endif
96 97
97#ifndef WEXITSTATUS 98#ifndef WEXITSTATUS
98 #define WEXITSTATUS(status) (((status) & 0xff00) >> 8) 99#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
99#endif 100#endif
100 101
101/* Thanks to the Cygwin project */ 102/* Thanks to the Cygwin project */
102#define ENOCSI 43 /* No CSI structure available */ 103#define ENOCSI 43 /* No CSI structure available */
103#define EL2HLT 44 /* Level 2 halted */ 104#define EL2HLT 44 /* Level 2 halted */
104#ifndef EDEADLK 105#ifndef EDEADLK
105 #define EDEADLK 45 /* Deadlock condition */ 106#define EDEADLK 45 /* Deadlock condition */
106#endif 107#endif
107#ifndef ENOLCK 108#ifndef ENOLCK
108 #define ENOLCK 46 /* No record locks available */ 109#define ENOLCK 46 /* No record locks available */
109#endif 110#endif
110#define EBADE 50 /* Invalid exchange */ 111#define EBADE 50 /* Invalid exchange */
111#define EBADR 51 /* Invalid request descriptor */ 112#define EBADR 51 /* Invalid request descriptor */
112#define EXFULL 52 /* Exchange full */ 113#define EXFULL 52 /* Exchange full */
113#define ENOANO 53 /* No anode */ 114#define ENOANO 53 /* No anode */
114#define EBADRQC 54 /* Invalid request code */ 115#define EBADRQC 54 /* Invalid request code */
115#define EBADSLT 55 /* Invalid slot */ 116#define EBADSLT 55 /* Invalid slot */
116#ifndef EDEADLOCK 117#ifndef EDEADLOCK
117 #define EDEADLOCK EDEADLK /* File locking deadlock error */ 118#define EDEADLOCK EDEADLK /* File locking deadlock error */
118#endif 119#endif
119#define EBFONT 57 /* Bad font file fmt */ 120#define EBFONT 57 /* Bad font file fmt */
120#define ENOSTR 60 /* Device not a stream */ 121#define ENOSTR 60 /* Device not a stream */
121#define ENODATA 61 /* No data (for no delay io) */ 122#define ENODATA 61 /* No data (for no delay io) */
122#define ETIME 62 /* Timer expired */ 123#define ETIME 62 /* Timer expired */
123#define ENOSR 63 /* Out of streams resources */ 124#define ENOSR 63 /* Out of streams resources */
124#define ENONET 64 /* Machine is not on the network */ 125#define ENONET 64 /* Machine is not on the network */
125#define ENOPKG 65 /* Package not installed */ 126#define ENOPKG 65 /* Package not installed */
126#define EREMOTE 66 /* The object is remote */ 127#define EREMOTE 66 /* The object is remote */
127#define ENOLINK 67 /* The link has been severed */ 128#define ENOLINK 67 /* The link has been severed */
128#define EADV 68 /* Advertise error */ 129#define EADV 68 /* Advertise error */
129#define ESRMNT 69 /* Srmount error */ 130#define ESRMNT 69 /* Srmount error */
130#define ECOMM 70 /* Communication error on send */ 131#define ECOMM 70 /* Communication error on send */
131#define EPROTO 71 /* Protocol error */ 132#define EPROTO 71 /* Protocol error */
132#define EMULTIHOP 74 /* Multihop attempted */ 133#define EMULTIHOP 74 /* Multihop attempted */
133#define ELBIN 75 /* Inode is remote (not really error) */ 134#define ELBIN 75 /* Inode is remote (not really error) */
134#define EDOTDOT 76 /* Cross mount point (not really error) */ 135#define EDOTDOT 76 /* Cross mount point (not really error) */
135#define EBADMSG 77 /* Trying to read unreadable message */ 136#define EBADMSG 77 /* Trying to read unreadable message */
136#define ENOTUNIQ 80 /* Given log. name not unique */ 137#define ENOTUNIQ 80 /* Given log. name not unique */
137#define EBADFD 81 /* f.d. invalid for this operation */ 138#define EBADFD 81 /* f.d. invalid for this operation */
138#define EREMCHG 82 /* Remote address changed */ 139#define EREMCHG 82 /* Remote address changed */
139#define ELIBACC 83 /* Can't access a needed shared lib */ 140#define ELIBACC 83 /* Can't access a needed shared lib */
140#define ELIBBAD 84 /* Accessing a corrupted shared lib */ 141#define ELIBBAD 84 /* Accessing a corrupted shared lib */
141#define ELIBSCN 85 /* .lib section in a.out corrupted */ 142#define ELIBSCN 85 /* .lib section in a.out corrupted */
142#define ELIBMAX 86 /* Attempting to link in too many libs */ 143#define ELIBMAX 86 /* Attempting to link in too many libs */
143#define ELIBEXEC 87 /* Attempting to exec a shared library */ 144#define ELIBEXEC 87 /* Attempting to exec a shared library */
144#ifndef ENOSYS 145#ifndef ENOSYS
145 #define ENOSYS 88 /* Function not implemented */ 146#define ENOSYS 88 /* Function not implemented */
146#endif 147#endif
147#define ENMFILE 89 /* No more files */ 148#define ENMFILE 89 /* No more files */
148#ifndef ENOTEMPTY 149#ifndef ENOTEMPTY
149 #define ENOTEMPTY 90 /* Directory not empty */ 150#define ENOTEMPTY 90 /* Directory not empty */
150#endif 151#endif
151#ifndef ENAMETOOLONG 152#ifndef ENAMETOOLONG
152 #define ENAMETOOLONG 91 /* File or path name too long */ 153#define ENAMETOOLONG 91 /* File or path name too long */
153#endif 154#endif
154#define ELOOP 92 /* Too many symbolic links */ 155#define ELOOP 92 /* Too many symbolic links */
155#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ 156#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
156#define EPFNOSUPPORT 96 /* Protocol family not supported */ 157#define EPFNOSUPPORT 96 /* Protocol family not supported */
157#define ECONNRESET 104 /* Connection reset by peer */ 158#define ECONNRESET 104 /* Connection reset by peer */
158#define ENOBUFS 105 /* No buffer space available */ 159#define ENOBUFS 105 /* No buffer space available */
159#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */ 160#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */
160#define EPROTOTYPE 107 /* Protocol wrong type for socket */ 161#define EPROTOTYPE 107 /* Protocol wrong type for socket */
161#define ENOTSOCK 108 /* Socket operation on non-socket */ 162#define ENOTSOCK 108 /* Socket operation on non-socket */
162#define ENOPROTOOPT 109 /* Protocol not available */ 163#define ENOPROTOOPT 109 /* Protocol not available */
163#define ESHUTDOWN 110 /* Can't send after socket shutdown */ 164#define ESHUTDOWN 110 /* Can't send after socket shutdown */
164#define ECONNREFUSED 111 /* Connection refused */ 165#define ECONNREFUSED 111 /* Connection refused */
165#define EADDRINUSE 112 /* Address already in use */ 166#define EADDRINUSE 112 /* Address already in use */
166#define ECONNABORTED 113 /* Connection aborted */ 167#define ECONNABORTED 113 /* Connection aborted */
167#define ENETUNREACH 114 /* Network is unreachable */ 168#define ENETUNREACH 114 /* Network is unreachable */
168#define ENETDOWN 115 /* Network interface is not configured */ 169#define ENETDOWN 115 /* Network interface is not configured */
169#ifndef ETIMEDOUT 170#ifndef ETIMEDOUT
170 #define ETIMEDOUT 116 /* Connection timed out */ 171#define ETIMEDOUT 116 /* Connection timed out */
171#endif 172#endif
172#define EHOSTDOWN 117 /* Host is down */ 173#define EHOSTDOWN 117 /* Host is down */
173#define EHOSTUNREACH 118 /* Host is unreachable */ 174#define EHOSTUNREACH 118 /* Host is unreachable */
174#define EINPROGRESS 119 /* Connection already in progress */ 175#define EINPROGRESS 119 /* Connection already in progress */
175#define EALREADY 120 /* Socket already connected */ 176#define EALREADY 120 /* Socket already connected */
176#define EDESTADDRREQ 121 /* Destination address required */ 177#define EDESTADDRREQ 121 /* Destination address required */
177#define EMSGSIZE 122 /* Message too long */ 178#define EMSGSIZE 122 /* Message too long */
178#define EPROTONOSUPPORT 123 /* Unknown protocol */ 179#define EPROTONOSUPPORT 123 /* Unknown protocol */
179#define ESOCKTNOSUPPORT 124 /* Socket type not supported */ 180#define ESOCKTNOSUPPORT 124 /* Socket type not supported */
180#define EADDRNOTAVAIL 125 /* Address not available */ 181#define EADDRNOTAVAIL 125 /* Address not available */
181#define ENETRESET 126 /* Connection aborted by network */ 182#define ENETRESET 126 /* Connection aborted by network */
182#define EISCONN 127 /* Socket is already connected */ 183#define EISCONN 127 /* Socket is already connected */
183#define ENOTCONN 128 /* Socket is not connected */ 184#define ENOTCONN 128 /* Socket is not connected */
184#define ETOOMANYREFS 129 /* Too many references: cannot splice */ 185#define ETOOMANYREFS 129 /* Too many references: cannot splice */
185#define EPROCLIM 130 /* Too many processes */ 186#define EPROCLIM 130 /* Too many processes */
186#define EUSERS 131 /* Too many users */ 187#define EUSERS 131 /* Too many users */
187#define EDQUOT 132 /* Disk quota exceeded */ 188#define EDQUOT 132 /* Disk quota exceeded */
188#define ESTALE 133 /* Unknown error */ 189#define ESTALE 133 /* Unknown error */
189#ifndef ENOTSUP 190#ifndef ENOTSUP
190 #define ENOTSUP 134 /* Not supported */ 191#define ENOTSUP 134 /* Not supported */
191#endif 192#endif
192#define ENOMEDIUM 135 /* No medium (in tape drive) */ 193#define ENOMEDIUM 135 /* No medium (in tape drive) */
193#define ENOSHARE 136 /* No such host or network path */ 194#define ENOSHARE 136 /* No such host or network path */
194#define ECASECLASH 137 /* Filename exists with different case */ 195#define ECASECLASH 137 /* Filename exists with different case */
195#define EWOULDBLOCK EAGAIN /* Operation would block */ 196#define EWOULDBLOCK EAGAIN /* Operation would block */
196#define EOVERFLOW 139 /* Value too large for defined data type */ 197#define EOVERFLOW 139 /* Value too large for defined data type */
197 198
198#undef HOST_NOT_FOUND 199#undef HOST_NOT_FOUND
199#define HOST_NOT_FOUND 1 200#define HOST_NOT_FOUND 1
@@ -207,65 +208,65 @@ struct stat64
207#define PROT_READ 0x1 208#define PROT_READ 0x1
208#define PROT_WRITE 0x2 209#define PROT_WRITE 0x2
209#define MAP_SHARED 0x1 210#define MAP_SHARED 0x1
210#define MAP_PRIVATE 0x2 /* unsupported */ 211#define MAP_PRIVATE 0x2 /* unsupported */
211#define MAP_FIXED 0x10 212#define MAP_FIXED 0x10
212#define MAP_FAILED ((void *)-1) 213#define MAP_FAILED ((void *)-1)
213 214
214struct statfs 215 struct statfs
215{ 216 {
216 long f_type; /* type of filesystem (see below) */ 217 long f_type; /* type of filesystem (see below) */
217 long f_bsize; /* optimal transfer block size */ 218 long f_bsize; /* optimal transfer block size */
218 long f_blocks; /* total data blocks in file system */ 219 long f_blocks; /* total data blocks in file system */
219 long f_bfree; /* free blocks in fs */ 220 long f_bfree; /* free blocks in fs */
220 long f_bavail; /* free blocks avail to non-superuser */ 221 long f_bavail; /* free blocks avail to non-superuser */
221 long f_files; /* total file nodes in file system */ 222 long f_files; /* total file nodes in file system */
222 long f_ffree; /* free file nodes in fs */ 223 long f_ffree; /* free file nodes in fs */
223 long f_fsid; /* file system id */ 224 long f_fsid; /* file system id */
224 long f_namelen; /* maximum length of filenames */ 225 long f_namelen; /* maximum length of filenames */
225 long f_spare[6]; /* spare for later */ 226 long f_spare[6]; /* spare for later */
226}; 227 };
227 228
228/* Taken from the Wine project <http://www.winehq.org> 229/* Taken from the Wine project <http://www.winehq.org>
229 /wine/include/winternl.h */ 230 /wine/include/winternl.h */
230enum SYSTEM_INFORMATION_CLASS 231 enum SYSTEM_INFORMATION_CLASS
231{ 232 {
232 SystemBasicInformation = 0, 233 SystemBasicInformation = 0,
233 Unknown1, 234 Unknown1,
234 SystemPerformanceInformation = 2, 235 SystemPerformanceInformation = 2,
235 SystemTimeOfDayInformation = 3, /* was SystemTimeInformation */ 236 SystemTimeOfDayInformation = 3, /* was SystemTimeInformation */
236 Unknown4, 237 Unknown4,
237 SystemProcessInformation = 5, 238 SystemProcessInformation = 5,
238 Unknown6, 239 Unknown6,
239 Unknown7, 240 Unknown7,
240 SystemProcessorPerformanceInformation = 8, 241 SystemProcessorPerformanceInformation = 8,
241 Unknown9, 242 Unknown9,
242 Unknown10, 243 Unknown10,
243 SystemDriverInformation, 244 SystemDriverInformation,
244 Unknown12, 245 Unknown12,
245 Unknown13, 246 Unknown13,
246 Unknown14, 247 Unknown14,
247 Unknown15, 248 Unknown15,
248 SystemHandleList, 249 SystemHandleList,
249 Unknown17, 250 Unknown17,
250 Unknown18, 251 Unknown18,
251 Unknown19, 252 Unknown19,
252 Unknown20, 253 Unknown20,
253 SystemCacheInformation, 254 SystemCacheInformation,
254 Unknown22, 255 Unknown22,
255 SystemInterruptInformation = 23, 256 SystemInterruptInformation = 23,
256 SystemExceptionInformation = 33, 257 SystemExceptionInformation = 33,
257 SystemRegistryQuotaInformation = 37, 258 SystemRegistryQuotaInformation = 37,
258 SystemLookasideInformation = 45 259 SystemLookasideInformation = 45
259}; 260 };
260 261
261typedef struct 262 typedef struct
262{ 263 {
263 LARGE_INTEGER IdleTime; 264 LARGE_INTEGER IdleTime;
264 LARGE_INTEGER KernelTime; 265 LARGE_INTEGER KernelTime;
265 LARGE_INTEGER UserTime; 266 LARGE_INTEGER UserTime;
266 LARGE_INTEGER Reserved1[2]; 267 LARGE_INTEGER Reserved1[2];
267 ULONG Reserved2; 268 ULONG Reserved2;
268} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; 269 } SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
269 270
270#define sleep(secs) (Sleep(secs * 1000)) 271#define sleep(secs) (Sleep(secs * 1000))
271 272
@@ -282,11 +283,11 @@ typedef struct
282#define SHUT_RDWR SD_BOTH 283#define SHUT_RDWR SD_BOTH
283 284
284/* Operations for flock() */ 285/* Operations for flock() */
285#define LOCK_SH 1 /* shared lock */ 286#define LOCK_SH 1 /* shared lock */
286#define LOCK_EX 2 /* exclusive lock */ 287#define LOCK_EX 2 /* exclusive lock */
287#define LOCK_NB 4 /* or'd with one of the above to prevent 288#define LOCK_NB 4 /* or'd with one of the above to prevent
288 blocking */ 289 blocking */
289#define LOCK_UN 8 /* remove lock */ 290#define LOCK_UN 8 /* remove lock */
290 291
291/* Not supported under MinGW */ 292/* Not supported under MinGW */
292#define S_IRGRP 0 293#define S_IRGRP 0
@@ -308,272 +309,273 @@ typedef struct
308 */ 309 */
309#define index(s, c) strchr(s, c) 310#define index(s, c) strchr(s, c)
310 311
311BOOL _plibc_CreateShortcut(const char *pszSrc, const char *pszDest); 312 BOOL _plibc_CreateShortcut (const char *pszSrc, const char *pszDest);
312BOOL _plibc_DereferenceShortcut(char *pszShortcut); 313 BOOL _plibc_DereferenceShortcut (char *pszShortcut);
313char *plibc_ChooseDir(char *pszTitle, unsigned long ulFlags); 314 char *plibc_ChooseDir (char *pszTitle, unsigned long ulFlags);
314char *plibc_ChooseFile(char *pszTitle, unsigned long ulFlags); 315 char *plibc_ChooseFile (char *pszTitle, unsigned long ulFlags);
315long QueryRegistry(HKEY hMainKey, char *pszKey, char *pszSubKey, 316 long QueryRegistry (HKEY hMainKey, char *pszKey, char *pszSubKey,
316 char *pszBuffer, long *pdLength); 317 char *pszBuffer, long *pdLength);
317 318
318BOOL __win_IsHandleMarkedAsBlocking(SOCKET hHandle); 319 BOOL __win_IsHandleMarkedAsBlocking (SOCKET hHandle);
319void __win_SetHandleBlockingMode(SOCKET s, BOOL bBlocking); 320 void __win_SetHandleBlockingMode (SOCKET s, BOOL bBlocking);
320void __win_DiscardHandleBlockingMode(SOCKET s); 321 void __win_DiscardHandleBlockingMode (SOCKET s);
321int _win_isSocketValid(int s); 322 int _win_isSocketValid (int s);
322int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows); 323 int plibc_conv_to_win_path (const char *pszUnix, char *pszWindows);
323 324
324typedef void (*TPanicProc) (int, char *); 325 typedef void (*TPanicProc) (int, char *);
325void plibc_set_panic_proc(TPanicProc proc); 326 void plibc_set_panic_proc (TPanicProc proc);
326 327
327int flock(int fd, int operation); 328 int flock (int fd, int operation);
328int fsync(int fildes); 329 int fsync (int fildes);
329int inet_pton(int af, const char *src, void *dst); 330 int inet_pton (int af, const char *src, void *dst);
330int inet_pton4(const char *src, u_char *dst, int pton); 331 int inet_pton4 (const char *src, u_char * dst, int pton);
331#if USE_IPV6 332#if USE_IPV6
332int inet_pton6(const char *src, u_char *dst); 333 int inet_pton6 (const char *src, u_char * dst);
333#endif 334#endif
334int truncate(const char *fname, int distance); 335 int truncate (const char *fname, int distance);
335int statfs(const char *path, struct statfs *buf); 336 int statfs (const char *path, struct statfs *buf);
336const char *hstrerror(int err); 337 const char *hstrerror (int err);
337void gettimeofday(struct timeval *tp, void *tzp); 338 void gettimeofday (struct timeval *tp, void *tzp);
338int mkstemp(char *tmplate); 339 int mkstemp (char *tmplate);
339char *strptime (const char *buf, const char *format, struct tm *tm); 340 char *strptime (const char *buf, const char *format, struct tm *tm);
340char *ctime(const time_t *clock); 341 char *ctime (const time_t * clock);
341char *ctime_r(const time_t *clock, char *buf); 342 char *ctime_r (const time_t * clock, char *buf);
342int plibc_init(char *pszOrg, char *pszApp); 343 int plibc_init (char *pszOrg, char *pszApp);
343void plibc_shutdown(); 344 void plibc_shutdown ();
344int plibc_initialized(); 345 int plibc_initialized ();
345int plibc_conv_to_win_path_ex(const char *pszUnix, char *pszWindows, int derefLinks); 346 int plibc_conv_to_win_path_ex (const char *pszUnix, char *pszWindows,
346void _SetErrnoFromWinError(long lWinError, char *pszCaller, int iLine); 347 int derefLinks);
347void SetErrnoFromWinsockError(long lWinError); 348 void _SetErrnoFromWinError (long lWinError, char *pszCaller, int iLine);
348void SetHErrnoFromWinError(long lWinError); 349 void SetErrnoFromWinsockError (long lWinError);
349void SetErrnoFromHRESULT(HRESULT hRes); 350 void SetHErrnoFromWinError (long lWinError);
350FILE *_win_fopen(const char *filename, const char *mode); 351 void SetErrnoFromHRESULT (HRESULT hRes);
351DIR *_win_opendir(const char *dirname); 352 FILE *_win_fopen (const char *filename, const char *mode);
352int _win_open(const char *filename, int oflag, ...); 353 DIR *_win_opendir (const char *dirname);
354 int _win_open (const char *filename, int oflag, ...);
353#ifdef ENABLE_NLS 355#ifdef ENABLE_NLS
354char *_win_bindtextdomain(const char *domainname, const char *dirname); 356 char *_win_bindtextdomain (const char *domainname, const char *dirname);
355#endif 357#endif
356int _win_chdir(const char *path); 358 int _win_chdir (const char *path);
357int _win_close(int fd); 359 int _win_close (int fd);
358int _win_creat(const char *path, mode_t mode); 360 int _win_creat (const char *path, mode_t mode);
359int _win_fstat(int handle, struct stat *buffer); 361 int _win_fstat (int handle, struct stat *buffer);
360int _win_pipe(int *phandles); 362 int _win_pipe (int *phandles);
361int _win_rmdir(const char *path); 363 int _win_rmdir (const char *path);
362int _win_access( const char *path, int mode ); 364 int _win_access (const char *path, int mode);
363int _win_chmod(const char *filename, int pmode); 365 int _win_chmod (const char *filename, int pmode);
364char *realpath(const char *file_name, char *resolved_name); 366 char *realpath (const char *file_name, char *resolved_name);
365long _win_random(void); 367 long _win_random (void);
366int _win_remove(const char *path); 368 int _win_remove (const char *path);
367int _win_rename(const char *oldname, const char *newname); 369 int _win_rename (const char *oldname, const char *newname);
368int _win_stat(const char *path, struct stat *buffer); 370 int _win_stat (const char *path, struct stat *buffer);
369int _win_stat64(const char *path, struct stat64 *buffer); 371 int _win_stat64 (const char *path, struct stat64 *buffer);
370int _win_unlink(const char *filename); 372 int _win_unlink (const char *filename);
371int _win_write(int fildes, const void *buf, size_t nbyte); 373 int _win_write (int fildes, const void *buf, size_t nbyte);
372int _win_read(int fildes, void *buf, size_t nbyte); 374 int _win_read (int fildes, void *buf, size_t nbyte);
373size_t _win_fwrite(const void *buffer, size_t size, size_t count, FILE *stream); 375 size_t _win_fwrite (const void *buffer, size_t size, size_t count,
374size_t _win_fread( void *buffer, size_t size, size_t count, FILE *stream ); 376 FILE * stream);
375int _win_symlink(const char *path1, const char *path2); 377 size_t _win_fread (void *buffer, size_t size, size_t count, FILE * stream);
376void *_win_mmap(void *start, size_t len, int access, int flags, int fd, 378 int _win_symlink (const char *path1, const char *path2);
377 unsigned long long offset); 379 void *_win_mmap (void *start, size_t len, int access, int flags, int fd,
378int _win_munmap(void *start, size_t length); 380 unsigned long long offset);
379int _win_lstat(const char *path, struct stat *buf); 381 int _win_munmap (void *start, size_t length);
380int _win_lstat64(const char *path, struct stat64 *buf); 382 int _win_lstat (const char *path, struct stat *buf);
381int _win_readlink(const char *path, char *buf, size_t bufsize); 383 int _win_lstat64 (const char *path, struct stat64 *buf);
382int _win_accept(SOCKET s, struct sockaddr *addr, int *addrlen); 384 int _win_readlink (const char *path, char *buf, size_t bufsize);
383int _win_printf(const char *format,...); 385 int _win_accept (SOCKET s, struct sockaddr *addr, int *addrlen);
384int _win_fprintf(FILE *f,const char *format,...); 386 int _win_printf (const char *format, ...);
385int _win_vprintf(const char *format, va_list ap); 387 int _win_fprintf (FILE * f, const char *format, ...);
386int _win_vfprintf(FILE *stream, const char *format, va_list arg_ptr); 388 int _win_vprintf (const char *format, va_list ap);
387int _win_vsprintf(char *dest,const char *format, va_list arg_ptr); 389 int _win_vfprintf (FILE * stream, const char *format, va_list arg_ptr);
388int _win_vsnprintf(char* str, size_t size, const char *format, va_list arg_ptr); 390 int _win_vsprintf (char *dest, const char *format, va_list arg_ptr);
389int _win_snprintf(char *str,size_t size,const char *format,...); 391 int _win_vsnprintf (char *str, size_t size, const char *format,
390int _win_sprintf(char *dest,const char *format,...); 392 va_list arg_ptr);
391int _win_vsscanf(const char* str, const char* format, va_list arg_ptr); 393 int _win_snprintf (char *str, size_t size, const char *format, ...);
392int _win_sscanf(const char *str, const char *format, ...); 394 int _win_sprintf (char *dest, const char *format, ...);
393int _win_vfscanf(FILE *stream, const char *format, va_list arg_ptr); 395 int _win_vsscanf (const char *str, const char *format, va_list arg_ptr);
394int _win_vscanf(const char *format, va_list arg_ptr); 396 int _win_sscanf (const char *str, const char *format, ...);
395int _win_scanf(const char *format, ...); 397 int _win_vfscanf (FILE * stream, const char *format, va_list arg_ptr);
396int _win_fscanf(FILE *stream, const char *format, ...); 398 int _win_vscanf (const char *format, va_list arg_ptr);
397pid_t _win_waitpid(pid_t pid, int *stat_loc, int options); 399 int _win_scanf (const char *format, ...);
398int _win_bind(SOCKET s, const struct sockaddr *name, int namelen); 400 int _win_fscanf (FILE * stream, const char *format, ...);
399int _win_connect(SOCKET s,const struct sockaddr *name, int namelen); 401 pid_t _win_waitpid (pid_t pid, int *stat_loc, int options);
400int _win_getpeername(SOCKET s, struct sockaddr *name, 402 int _win_bind (SOCKET s, const struct sockaddr *name, int namelen);
401 int *namelen); 403 int _win_connect (SOCKET s, const struct sockaddr *name, int namelen);
402int _win_getsockname(SOCKET s, struct sockaddr *name, 404 int _win_getpeername (SOCKET s, struct sockaddr *name, int *namelen);
403 int *namelen); 405 int _win_getsockname (SOCKET s, struct sockaddr *name, int *namelen);
404int _win_getsockopt(SOCKET s, int level, int optname, char *optval, 406 int _win_getsockopt (SOCKET s, int level, int optname, char *optval,
405 int *optlen); 407 int *optlen);
406int _win_listen(SOCKET s, int backlog); 408 int _win_listen (SOCKET s, int backlog);
407int _win_recv(SOCKET s, char *buf, int len, int flags); 409 int _win_recv (SOCKET s, char *buf, int len, int flags);
408int _win_recvfrom(SOCKET s, void *buf, int len, int flags, 410 int _win_recvfrom (SOCKET s, void *buf, int len, int flags,
409 struct sockaddr *from, int *fromlen); 411 struct sockaddr *from, int *fromlen);
410int _win_select(int max_fd, fd_set * rfds, fd_set * wfds, fd_set * efds, 412 int _win_select (int max_fd, fd_set * rfds, fd_set * wfds, fd_set * efds,
411 const struct timeval *tv); 413 const struct timeval *tv);
412int _win_send(SOCKET s, const char *buf, int len, int flags); 414 int _win_send (SOCKET s, const char *buf, int len, int flags);
413int _win_sendto(SOCKET s, const char *buf, int len, int flags, 415 int _win_sendto (SOCKET s, const char *buf, int len, int flags,
414 const struct sockaddr *to, int tolen); 416 const struct sockaddr *to, int tolen);
415int _win_setsockopt(SOCKET s, int level, int optname, const void *optval, 417 int _win_setsockopt (SOCKET s, int level, int optname, const void *optval,
416 int optlen); 418 int optlen);
417int _win_shutdown(SOCKET s, int how); 419 int _win_shutdown (SOCKET s, int how);
418SOCKET _win_socket(int af, int type, int protocol); 420 SOCKET _win_socket (int af, int type, int protocol);
419struct hostent *_win_gethostbyaddr(const char *addr, int len, int type); 421 struct hostent *_win_gethostbyaddr (const char *addr, int len, int type);
420struct hostent *_win_gethostbyname(const char *name); 422 struct hostent *_win_gethostbyname (const char *name);
421char *_win_strerror(int errnum); 423 char *_win_strerror (int errnum);
422int IsWinNT(); 424 int IsWinNT ();
423 425
424#if !HAVE_STRNDUP 426#if !HAVE_STRNDUP
425char *strndup (const char *s, size_t n); 427 char *strndup (const char *s, size_t n);
426#endif 428#endif
427#if !HAVE_STRNLEN 429#if !HAVE_STRNLEN
428size_t strnlen (const char *str, size_t maxlen); 430 size_t strnlen (const char *str, size_t maxlen);
429#endif 431#endif
430 432
431#define strcasecmp(a, b) stricmp(a, b) 433#define strcasecmp(a, b) stricmp(a, b)
432#define strncasecmp(a, b, c) strnicmp(a, b, c) 434#define strncasecmp(a, b, c) strnicmp(a, b, c)
433 435
434#endif /* WINDOWS */ 436#endif /* WINDOWS */
435 437
436#ifndef WINDOWS 438#ifndef WINDOWS
437 #define DIR_SEPARATOR '/' 439#define DIR_SEPARATOR '/'
438 #define DIR_SEPARATOR_STR "/" 440#define DIR_SEPARATOR_STR "/"
439 #define PATH_SEPARATOR ';' 441#define PATH_SEPARATOR ';'
440 #define PATH_SEPARATOR_STR ";" 442#define PATH_SEPARATOR_STR ";"
441 #define NEWLINE "\n" 443#define NEWLINE "\n"
442 444
443#ifdef ENABLE_NLS 445#ifdef ENABLE_NLS
444 #define BINDTEXTDOMAIN(d, n) bindtextdomain(d, n) 446#define BINDTEXTDOMAIN(d, n) bindtextdomain(d, n)
445#endif 447#endif
446 #define CREAT(p, m) creat(p, m) 448#define CREAT(p, m) creat(p, m)
447 #undef FOPEN 449#undef FOPEN
448 #define FOPEN(f, m) fopen(f, m) 450#define FOPEN(f, m) fopen(f, m)
449 #define OPENDIR(d) opendir(d) 451#define OPENDIR(d) opendir(d)
450 #define OPEN(f) open(f) 452#define OPEN(f) open(f)
451 #define CHDIR(d) chdir(d) 453#define CHDIR(d) chdir(d)
452 #define CLOSE(f) close(f) 454#define CLOSE(f) close(f)
453 #define RMDIR(f) rmdir(f) 455#define RMDIR(f) rmdir(f)
454 #define ACCESS(p, m) access(p, m) 456#define ACCESS(p, m) access(p, m)
455 #define CHMOD(f, p) chmod(f, p) 457#define CHMOD(f, p) chmod(f, p)
456 #define FSTAT(h, b) fstat(h, b) 458#define FSTAT(h, b) fstat(h, b)
457 #define PIPE(h) pipe(h) 459#define PIPE(h) pipe(h)
458 #define REMOVE(p) remove(p) 460#define REMOVE(p) remove(p)
459 #define RENAME(o, n) rename(o, n) 461#define RENAME(o, n) rename(o, n)
460 #define STAT(p, b) stat(p, b) 462#define STAT(p, b) stat(p, b)
461 #define STAT64(p, b) stat64(p, b) 463#define STAT64(p, b) stat64(p, b)
462 #define UNLINK(f) unlink(f) 464#define UNLINK(f) unlink(f)
463 #define WRITE(f, b, n) write(f, b, n) 465#define WRITE(f, b, n) write(f, b, n)
464 #define READ(f, b, n) read(f, b, n) 466#define READ(f, b, n) read(f, b, n)
465 #define GN_FREAD(b, s, c, f) fread(b, s, c, f) 467#define GN_FREAD(b, s, c, f) fread(b, s, c, f)
466 #define GN_FWRITE(b, s, c, f) fwrite(b, s, c, f) 468#define GN_FWRITE(b, s, c, f) fwrite(b, s, c, f)
467 #define SYMLINK(a, b) symlink(a, b) 469#define SYMLINK(a, b) symlink(a, b)
468 #define MMAP(s, l, p, f, d, o) mmap(s, l, p, f, d, o) 470#define MMAP(s, l, p, f, d, o) mmap(s, l, p, f, d, o)
469 #define MUNMAP(s, l) munmap(s, l) 471#define MUNMAP(s, l) munmap(s, l)
470 #define STRERROR(i) strerror(i) 472#define STRERROR(i) strerror(i)
471 #define RANDOM() random() 473#define RANDOM() random()
472 #define READLINK(p, b, s) readlink(p, b, s) 474#define READLINK(p, b, s) readlink(p, b, s)
473 #define LSTAT(p, b) lstat(p, b) 475#define LSTAT(p, b) lstat(p, b)
474 #define LSTAT64(p, b) lstat64(p, b) 476#define LSTAT64(p, b) lstat64(p, b)
475 #define PRINTF printf 477#define PRINTF printf
476 #define FPRINTF fprintf 478#define FPRINTF fprintf
477 #define VPRINTF(f, a) vprintf(f, a) 479#define VPRINTF(f, a) vprintf(f, a)
478 #define VFPRINTF(s, f, a) vfprintf(s, f, a) 480#define VFPRINTF(s, f, a) vfprintf(s, f, a)
479 #define VSPRINTF(d, f, a) vsprintf(d, f, a) 481#define VSPRINTF(d, f, a) vsprintf(d, f, a)
480 #define VSNPRINTF(str, size, fmt, a) vsnprintf(str, size, fmt, a) 482#define VSNPRINTF(str, size, fmt, a) vsnprintf(str, size, fmt, a)
481 #define _REAL_SNPRINTF snprintf 483#define _REAL_SNPRINTF snprintf
482 #define SPRINTF sprintf 484#define SPRINTF sprintf
483 #define VSSCANF(s, f, a) vsscanf(s, f, a) 485#define VSSCANF(s, f, a) vsscanf(s, f, a)
484 #define SSCANF sscanf 486#define SSCANF sscanf
485 #define VFSCANF(s, f, a) vfscanf(s, f, a) 487#define VFSCANF(s, f, a) vfscanf(s, f, a)
486 #define VSCANF(f, a) vscanf(f, a) 488#define VSCANF(f, a) vscanf(f, a)
487 #define SCANF scanf 489#define SCANF scanf
488 #define FSCANF fscanf 490#define FSCANF fscanf
489 #define WAITPID(p, s, o) waitpid(p, s, o) 491#define WAITPID(p, s, o) waitpid(p, s, o)
490 #define ACCEPT(s, a, l) accept(s, a, l) 492#define ACCEPT(s, a, l) accept(s, a, l)
491 #define BIND(s, n, l) bind(s, n, l) 493#define BIND(s, n, l) bind(s, n, l)
492 #define CONNECT(s, n, l) connect(s, n, l) 494#define CONNECT(s, n, l) connect(s, n, l)
493 #define GETPEERNAME(s, n, l) getpeername(s, n, l) 495#define GETPEERNAME(s, n, l) getpeername(s, n, l)
494 #define GETSOCKNAME(s, n, l) getsockname(s, n, l) 496#define GETSOCKNAME(s, n, l) getsockname(s, n, l)
495 #define GETSOCKOPT(s, l, o, v, p) getsockopt(s, l, o, v, p) 497#define GETSOCKOPT(s, l, o, v, p) getsockopt(s, l, o, v, p)
496 #define LISTEN(s, b) listen(s, b) 498#define LISTEN(s, b) listen(s, b)
497 #define RECV(s, b, l, f) recv(s, b, l, f) 499#define RECV(s, b, l, f) recv(s, b, l, f)
498 #define RECVFROM(s, b, l, f, r, o) recvfrom(s, b, l, f, r, o) 500#define RECVFROM(s, b, l, f, r, o) recvfrom(s, b, l, f, r, o)
499 #define SELECT(n, r, w, e, t) select(n, r, w, e, t) 501#define SELECT(n, r, w, e, t) select(n, r, w, e, t)
500 #define SEND(s, b, l, f) send(s, b, l, f) 502#define SEND(s, b, l, f) send(s, b, l, f)
501 #define SENDTO(s, b, l, f, o, n) sendto(s, b, l, f, o, n) 503#define SENDTO(s, b, l, f, o, n) sendto(s, b, l, f, o, n)
502 #define SETSOCKOPT(s, l, o, v, n) setsockopt(s, l, o, v, n) 504#define SETSOCKOPT(s, l, o, v, n) setsockopt(s, l, o, v, n)
503 #define SHUTDOWN(s, h) shutdown(s, h) 505#define SHUTDOWN(s, h) shutdown(s, h)
504 #define SOCKET(a, t, p) socket(a, t, p) 506#define SOCKET(a, t, p) socket(a, t, p)
505 #define GETHOSTBYADDR(a, l, t) gethostbyname(a, l, t) 507#define GETHOSTBYADDR(a, l, t) gethostbyname(a, l, t)
506 #define GETHOSTBYNAME(n) gethostbyname(n) 508#define GETHOSTBYNAME(n) gethostbyname(n)
507#else 509#else
508 #define DIR_SEPARATOR '\\' 510#define DIR_SEPARATOR '\\'
509 #define DIR_SEPARATOR_STR "\\" 511#define DIR_SEPARATOR_STR "\\"
510 #define PATH_SEPARATOR ':' 512#define PATH_SEPARATOR ':'
511 #define PATH_SEPARATOR_STR ":" 513#define PATH_SEPARATOR_STR ":"
512 #define NEWLINE "\r\n" 514#define NEWLINE "\r\n"
513 515
514#ifdef ENABLE_NLS 516#ifdef ENABLE_NLS
515 #define BINDTEXTDOMAIN(d, n) _win_bindtextdomain(d, n) 517#define BINDTEXTDOMAIN(d, n) _win_bindtextdomain(d, n)
516#endif 518#endif
517 #define CREAT(p, m) _win_creat(p, m) 519#define CREAT(p, m) _win_creat(p, m)
518 #define FOPEN(f, m) _win_fopen(f, m) 520#define FOPEN(f, m) _win_fopen(f, m)
519 #define OPENDIR(d) _win_opendir(d) 521#define OPENDIR(d) _win_opendir(d)
520 #define OPEN(f) _win_open(f) 522#define OPEN(f) _win_open(f)
521 #define CHDIR(d) _win_chdir(d) 523#define CHDIR(d) _win_chdir(d)
522 #define CLOSE(f) _win_close(f) 524#define CLOSE(f) _win_close(f)
523 #define FSTAT(h, b) _win_fstat(h, b) 525#define FSTAT(h, b) _win_fstat(h, b)
524 #define RMDIR(f) _win_rmdir(f) 526#define RMDIR(f) _win_rmdir(f)
525 #define ACCESS(p, m) _win_access(p, m) 527#define ACCESS(p, m) _win_access(p, m)
526 #define CHMOD(f, p) _win_chmod(f, p) 528#define CHMOD(f, p) _win_chmod(f, p)
527 #define PIPE(h) _win_pipe(h) 529#define PIPE(h) _win_pipe(h)
528 #define RANDOM() _win_random() 530#define RANDOM() _win_random()
529 #define REMOVE(p) _win_remove(p) 531#define REMOVE(p) _win_remove(p)
530 #define RENAME(o, n) _win_rename(o, n) 532#define RENAME(o, n) _win_rename(o, n)
531 #define STAT(p, b) _win_stat(p, b) 533#define STAT(p, b) _win_stat(p, b)
532 #define STAT64(p, b) _win_stat64(p, b) 534#define STAT64(p, b) _win_stat64(p, b)
533 #define UNLINK(f) _win_unlink(f) 535#define UNLINK(f) _win_unlink(f)
534 #define WRITE(f, b, n) _win_write(f, b, n) 536#define WRITE(f, b, n) _win_write(f, b, n)
535 #define READ(f, b, n) _win_read(f, b, n) 537#define READ(f, b, n) _win_read(f, b, n)
536 #define GN_FREAD(b, s, c, f) _win_fread(b, s, c, f) 538#define GN_FREAD(b, s, c, f) _win_fread(b, s, c, f)
537 #define GN_FWRITE(b, s, c, f) _win_fwrite(b, s, c, f) 539#define GN_FWRITE(b, s, c, f) _win_fwrite(b, s, c, f)
538 #define SYMLINK(a, b) _win_symlink(a, b) 540#define SYMLINK(a, b) _win_symlink(a, b)
539 #define MMAP(s, l, p, f, d, o) _win_mmap(s, l, p, f, d, o) 541#define MMAP(s, l, p, f, d, o) _win_mmap(s, l, p, f, d, o)
540 #define MUNMAP(s, l) _win_munmap(s, l) 542#define MUNMAP(s, l) _win_munmap(s, l)
541 #define STRERROR(i) _win_strerror(i) 543#define STRERROR(i) _win_strerror(i)
542 #define READLINK(p, b, s) _win_readlink(p, b, s) 544#define READLINK(p, b, s) _win_readlink(p, b, s)
543 #define LSTAT(p, b) _win_lstat(p, b) 545#define LSTAT(p, b) _win_lstat(p, b)
544 #define LSTAT64(p, b) _win_lstat64(p, b) 546#define LSTAT64(p, b) _win_lstat64(p, b)
545 #define PRINTF(f, ...) _win_printf(f , __VA_ARGS__) 547#define PRINTF(f, ...) _win_printf(f , __VA_ARGS__)
546 #define FPRINTF(fil, fmt, ...) _win_fprintf(fil, fmt, __VA_ARGS__) 548#define FPRINTF(fil, fmt, ...) _win_fprintf(fil, fmt, __VA_ARGS__)
547 #define VPRINTF(f, a) _win_vprintf(f, a) 549#define VPRINTF(f, a) _win_vprintf(f, a)
548 #define VFPRINTF(s, f, a) _win_vfprintf(s, f, a) 550#define VFPRINTF(s, f, a) _win_vfprintf(s, f, a)
549 #define VSPRINTF(d, f, a) _win_vsprintf(d, f, a) 551#define VSPRINTF(d, f, a) _win_vsprintf(d, f, a)
550 #define VSNPRINTF(str, size, fmt, a) _win_vsnprintf(str, size, fmt, a) 552#define VSNPRINTF(str, size, fmt, a) _win_vsnprintf(str, size, fmt, a)
551 #define _REAL_SNPRINTF(str, size, fmt, ...) _win_snprintf(str, size, fmt, __VA_ARGS__) 553#define _REAL_SNPRINTF(str, size, fmt, ...) _win_snprintf(str, size, fmt, __VA_ARGS__)
552 #define SPRINTF(d, f, ...) _win_sprintf(d, f, __VA_ARGS__) 554#define SPRINTF(d, f, ...) _win_sprintf(d, f, __VA_ARGS__)
553 #define VSSCANF(s, f, a) _win_vsscanf(s, f, a) 555#define VSSCANF(s, f, a) _win_vsscanf(s, f, a)
554 #define SSCANF(s, f, ...) _win_sscanf(s, f, __VA_ARGS__) 556#define SSCANF(s, f, ...) _win_sscanf(s, f, __VA_ARGS__)
555 #define VFSCANF(s, f, a) _win_vfscanf(s, f, a) 557#define VFSCANF(s, f, a) _win_vfscanf(s, f, a)
556 #define VSCANF(f, a) _win_vscanf(f, a) 558#define VSCANF(f, a) _win_vscanf(f, a)
557 #define SCANF(f, ...) _win_scanf(f, __VA_ARGS__) 559#define SCANF(f, ...) _win_scanf(f, __VA_ARGS__)
558 #define FSCANF(s, f, ...) _win_fscanf(s, f, __VA_ARGS__) 560#define FSCANF(s, f, ...) _win_fscanf(s, f, __VA_ARGS__)
559 #define WAITPID(p, s, o) _win_waitpid(p, s, o) 561#define WAITPID(p, s, o) _win_waitpid(p, s, o)
560 #define ACCEPT(s, a, l) _win_accept(s, a, l) 562#define ACCEPT(s, a, l) _win_accept(s, a, l)
561 #define BIND(s, n, l) _win_bind(s, n, l) 563#define BIND(s, n, l) _win_bind(s, n, l)
562 #define CONNECT(s, n, l) _win_connect(s, n, l) 564#define CONNECT(s, n, l) _win_connect(s, n, l)
563 #define GETPEERNAME(s, n, l) _win_getpeername(s, n, l) 565#define GETPEERNAME(s, n, l) _win_getpeername(s, n, l)
564 #define GETSOCKNAME(s, n, l) _win_getsockname(s, n, l) 566#define GETSOCKNAME(s, n, l) _win_getsockname(s, n, l)
565 #define GETSOCKOPT(s, l, o, v, p) _win_getsockopt(s, l, o, v, p) 567#define GETSOCKOPT(s, l, o, v, p) _win_getsockopt(s, l, o, v, p)
566 #define LISTEN(s, b) _win_listen(s, b) 568#define LISTEN(s, b) _win_listen(s, b)
567 #define RECV(s, b, l, f) _win_recv(s, b, l, f) 569#define RECV(s, b, l, f) _win_recv(s, b, l, f)
568 #define RECVFROM(s, b, l, f, r, o) _win_recvfrom(s, b, l, f, r, o) 570#define RECVFROM(s, b, l, f, r, o) _win_recvfrom(s, b, l, f, r, o)
569 #define SELECT(n, r, w, e, t) _win_select(n, r, w, e, t) 571#define SELECT(n, r, w, e, t) _win_select(n, r, w, e, t)
570 #define SEND(s, b, l, f) _win_send(s, b, l, f) 572#define SEND(s, b, l, f) _win_send(s, b, l, f)
571 #define SENDTO(s, b, l, f, o, n) _win_sendto(s, b, l, f, o, n) 573#define SENDTO(s, b, l, f, o, n) _win_sendto(s, b, l, f, o, n)
572 #define SETSOCKOPT(s, l, o, v, n) _win_setsockopt(s, l, o, v, n) 574#define SETSOCKOPT(s, l, o, v, n) _win_setsockopt(s, l, o, v, n)
573 #define SHUTDOWN(s, h) _win_shutdown(s, h) 575#define SHUTDOWN(s, h) _win_shutdown(s, h)
574 #define SOCKET(a, t, p) _win_socket(a, t, p) 576#define SOCKET(a, t, p) _win_socket(a, t, p)
575 #define GETHOSTBYADDR(a, l, t) _win_gethostbyname(a, l, t) 577#define GETHOSTBYADDR(a, l, t) _win_gethostbyname(a, l, t)
576 #define GETHOSTBYNAME(n) _win_gethostbyname(n) 578#define GETHOSTBYNAME(n) _win_gethostbyname(n)
577#endif 579#endif
578 580
579 581
@@ -582,6 +584,6 @@ size_t strnlen (const char *str, size_t maxlen);
582#endif 584#endif
583 585
584 586
585#endif //_PLIBC_H_ 587#endif //_PLIBC_H_
586 588
587/* end of plibc.h */ 589/* end of plibc.h */
diff --git a/src/daemon/response.c b/src/daemon/response.c
index 0326a15b..412bf2ea 100644
--- a/src/daemon/response.c
+++ b/src/daemon/response.c
@@ -34,26 +34,25 @@
34 * @return MHD_NO on error (i.e. invalid header or content format). 34 * @return MHD_NO on error (i.e. invalid header or content format).
35 */ 35 */
36int 36int
37MHD_add_response_header(struct MHD_Response * response, 37MHD_add_response_header (struct MHD_Response *response,
38 const char * header, 38 const char *header, const char *content)
39 const char * content) { 39{
40 struct MHD_HTTP_Header * hdr; 40 struct MHD_HTTP_Header *hdr;
41 41
42 if ( (response == NULL) || 42 if ((response == NULL) ||
43 (header == NULL) || 43 (header == NULL) ||
44 (content == NULL) || 44 (content == NULL) ||
45 (strlen(header) == 0) || 45 (strlen (header) == 0) ||
46 (strlen(content) == 0) || 46 (strlen (content) == 0) ||
47 (NULL != strstr(header, "\t")) || 47 (NULL != strstr (header, "\t")) ||
48 (NULL != strstr(header, "\r")) || 48 (NULL != strstr (header, "\r")) ||
49 (NULL != strstr(header, "\n")) || 49 (NULL != strstr (header, "\n")) ||
50 (NULL != strstr(content, "\t")) || 50 (NULL != strstr (content, "\t")) ||
51 (NULL != strstr(content, "\r")) || 51 (NULL != strstr (content, "\r")) || (NULL != strstr (content, "\n")))
52 (NULL != strstr(content, "\n")) )
53 return MHD_NO; 52 return MHD_NO;
54 hdr = malloc(sizeof(struct MHD_HTTP_Header)); 53 hdr = malloc (sizeof (struct MHD_HTTP_Header));
55 hdr->header = strdup(header); 54 hdr->header = strdup (header);
56 hdr->value = strdup(content); 55 hdr->value = strdup (content);
57 hdr->kind = MHD_HEADER_KIND; 56 hdr->kind = MHD_HEADER_KIND;
58 hdr->next = response->first_header; 57 hdr->next = response->first_header;
59 response->first_header = hdr; 58 response->first_header = hdr;
@@ -66,32 +65,33 @@ MHD_add_response_header(struct MHD_Response * response,
66 * @return MHD_NO on error (no such header known) 65 * @return MHD_NO on error (no such header known)
67 */ 66 */
68int 67int
69MHD_del_response_header(struct MHD_Response * response, 68MHD_del_response_header (struct MHD_Response *response,
70 const char * header, 69 const char *header, const char *content)
71 const char * content) { 70{
72 struct MHD_HTTP_Header * pos; 71 struct MHD_HTTP_Header *pos;
73 struct MHD_HTTP_Header * prev; 72 struct MHD_HTTP_Header *prev;
74 73
75 if ( (header == NULL) || 74 if ((header == NULL) || (content == NULL))
76 (content == NULL) )
77 return MHD_NO; 75 return MHD_NO;
78 prev = NULL; 76 prev = NULL;
79 pos = response->first_header; 77 pos = response->first_header;
80 while (pos != NULL) { 78 while (pos != NULL)
81 if ( (0 == strcmp(header, pos->header)) && 79 {
82 (0 == strcmp(content, pos->value)) ) { 80 if ((0 == strcmp (header, pos->header)) &&
83 free(pos->header); 81 (0 == strcmp (content, pos->value)))
84 free(pos->value); 82 {
85 if (prev == NULL) 83 free (pos->header);
86 response->first_header = pos->next; 84 free (pos->value);
87 else 85 if (prev == NULL)
88 prev->next = pos->next; 86 response->first_header = pos->next;
89 free(pos); 87 else
90 return MHD_YES; 88 prev->next = pos->next;
89 free (pos);
90 return MHD_YES;
91 }
92 prev = pos;
93 pos = pos->next;
91 } 94 }
92 prev = pos;
93 pos = pos->next;
94 }
95 return MHD_NO; 95 return MHD_NO;
96} 96}
97 97
@@ -104,22 +104,21 @@ MHD_del_response_header(struct MHD_Response * response,
104 * @return number of entries iterated over 104 * @return number of entries iterated over
105 */ 105 */
106int 106int
107MHD_get_response_headers(struct MHD_Response * response, 107MHD_get_response_headers (struct MHD_Response *response,
108 MHD_KeyValueIterator iterator, 108 MHD_KeyValueIterator iterator, void *iterator_cls)
109 void * iterator_cls) { 109{
110 struct MHD_HTTP_Header * pos; 110 struct MHD_HTTP_Header *pos;
111 int numHeaders = 0; 111 int numHeaders = 0;
112 pos = response->first_header; 112 pos = response->first_header;
113 while (pos != NULL) { 113 while (pos != NULL)
114 numHeaders++; 114 {
115 if ( (iterator != NULL) && 115 numHeaders++;
116 (MHD_YES != iterator(iterator_cls, 116 if ((iterator != NULL) &&
117 pos->kind, 117 (MHD_YES != iterator (iterator_cls,
118 pos->header, 118 pos->kind, pos->header, pos->value)))
119 pos->value)) ) 119 break;
120 break; 120 pos = pos->next;
121 pos = pos->next; 121 }
122 }
123 return numHeaders; 122 return numHeaders;
124} 123}
125 124
@@ -131,16 +130,16 @@ MHD_get_response_headers(struct MHD_Response * response,
131 * @return NULL if header does not exist 130 * @return NULL if header does not exist
132 */ 131 */
133const char * 132const char *
134MHD_get_response_header(struct MHD_Response * response, 133MHD_get_response_header (struct MHD_Response *response, const char *key)
135 const char * key) { 134{
136 struct MHD_HTTP_Header * pos; 135 struct MHD_HTTP_Header *pos;
137 pos = response->first_header; 136 pos = response->first_header;
138 while (pos != NULL) { 137 while (pos != NULL)
139 if (0 == strcmp(key, 138 {
140 pos->header)) 139 if (0 == strcmp (key, pos->header))
141 return pos->value; 140 return pos->value;
142 pos = pos->next; 141 pos = pos->next;
143 } 142 }
144 return NULL; 143 return NULL;
145} 144}
146 145
@@ -156,29 +155,30 @@ MHD_get_response_header(struct MHD_Response * response,
156 * @return NULL on error (i.e. invalid arguments, out of memory) 155 * @return NULL on error (i.e. invalid arguments, out of memory)
157 */ 156 */
158struct MHD_Response * 157struct MHD_Response *
159MHD_create_response_from_callback(size_t size, 158MHD_create_response_from_callback (size_t size,
160 MHD_ContentReaderCallback crc, 159 MHD_ContentReaderCallback crc,
161 void * crc_cls, 160 void *crc_cls,
162 MHD_ContentReaderFreeCallback crfc) { 161 MHD_ContentReaderFreeCallback crfc)
163 struct MHD_Response * retVal; 162{
163 struct MHD_Response *retVal;
164 164
165 if (crc == NULL) 165 if (crc == NULL)
166 return NULL; 166 return NULL;
167 retVal = malloc(sizeof(struct MHD_Response)); 167 retVal = malloc (sizeof (struct MHD_Response));
168 memset(retVal, 168 memset (retVal, 0, sizeof (struct MHD_Response));
169 0, 169 retVal->data = malloc (MHD_BUF_INC_SIZE);
170 sizeof(struct MHD_Response)); 170 if (retVal->data == NULL)
171 retVal->data = malloc(MHD_BUF_INC_SIZE); 171 {
172 if (retVal->data == NULL) { 172 free (retVal);
173 free(retVal); 173 return NULL;
174 return NULL; 174 }
175 }
176 retVal->data_buffer_size = MHD_BUF_INC_SIZE; 175 retVal->data_buffer_size = MHD_BUF_INC_SIZE;
177 if (pthread_mutex_init(&retVal->mutex, NULL) != 0) { 176 if (pthread_mutex_init (&retVal->mutex, NULL) != 0)
178 free(retVal->data); 177 {
179 free(retVal); 178 free (retVal->data);
180 return NULL; 179 free (retVal);
181 } 180 return NULL;
181 }
182 retVal->crc = crc; 182 retVal->crc = crc;
183 retVal->crfc = crfc; 183 retVal->crfc = crfc;
184 retVal->crc_cls = crc_cls; 184 retVal->crc_cls = crc_cls;
@@ -200,33 +200,28 @@ MHD_create_response_from_callback(size_t size,
200 * @return NULL on error (i.e. invalid arguments, out of memory) 200 * @return NULL on error (i.e. invalid arguments, out of memory)
201 */ 201 */
202struct MHD_Response * 202struct MHD_Response *
203MHD_create_response_from_data(size_t size, 203MHD_create_response_from_data (size_t size,
204 void * data, 204 void *data, int must_free, int must_copy)
205 int must_free, 205{
206 int must_copy) { 206 struct MHD_Response *retVal;
207 struct MHD_Response * retVal; 207 void *tmp;
208 void * tmp;
209 208
210 if ( (data == NULL) && 209 if ((data == NULL) && (size > 0))
211 (size > 0) )
212 return NULL; 210 return NULL;
213 retVal = malloc(sizeof(struct MHD_Response)); 211 retVal = malloc (sizeof (struct MHD_Response));
214 memset(retVal, 212 memset (retVal, 0, sizeof (struct MHD_Response));
215 0, 213 if (pthread_mutex_init (&retVal->mutex, NULL) != 0)
216 sizeof(struct MHD_Response)); 214 {
217 if (pthread_mutex_init(&retVal->mutex, NULL) != 0) { 215 free (retVal);
218 free(retVal); 216 return NULL;
219 return NULL; 217 }
220 } 218 if ((must_copy) && (size > 0))
221 if ( (must_copy) && 219 {
222 (size > 0) ) { 220 tmp = malloc (size);
223 tmp = malloc(size); 221 memcpy (tmp, data, size);
224 memcpy(tmp, 222 must_free = 1;
225 data, 223 data = tmp;
226 size); 224 }
227 must_free = 1;
228 data = tmp;
229 }
230 retVal->crc = NULL; 225 retVal->crc = NULL;
231 retVal->crfc = must_free ? &free : NULL; 226 retVal->crfc = must_free ? &free : NULL;
232 retVal->crc_cls = must_free ? data : NULL; 227 retVal->crc_cls = must_free ? data : NULL;
@@ -244,38 +239,42 @@ MHD_create_response_from_data(size_t size,
244 * necessarily be freed immediatley. 239 * necessarily be freed immediatley.
245 */ 240 */
246void 241void
247MHD_destroy_response(struct MHD_Response * response) { 242MHD_destroy_response (struct MHD_Response *response)
248 struct MHD_HTTP_Header * pos; 243{
244 struct MHD_HTTP_Header *pos;
249 245
250 if (response == NULL) 246 if (response == NULL)
251 return;
252 pthread_mutex_lock(&response->mutex);
253 if (0 != --response->reference_count) {
254 pthread_mutex_unlock(&response->mutex);
255 return; 247 return;
256 } 248 pthread_mutex_lock (&response->mutex);
257 pthread_mutex_unlock(&response->mutex); 249 if (0 != --response->reference_count)
258 pthread_mutex_destroy(&response->mutex); 250 {
251 pthread_mutex_unlock (&response->mutex);
252 return;
253 }
254 pthread_mutex_unlock (&response->mutex);
255 pthread_mutex_destroy (&response->mutex);
259 if (response->crfc != NULL) 256 if (response->crfc != NULL)
260 response->crfc(response->crc_cls); 257 response->crfc (response->crc_cls);
261 while (response->first_header != NULL) { 258 while (response->first_header != NULL)
262 pos = response->first_header; 259 {
263 response->first_header = pos->next; 260 pos = response->first_header;
264 free(pos->header); 261 response->first_header = pos->next;
265 free(pos->value); 262 free (pos->header);
266 free(pos); 263 free (pos->value);
267 } 264 free (pos);
268 if (response->crc != NULL) 265 }
269 free(response->data); 266 if (response->crc != NULL)
270 free(response); 267 free (response->data);
268 free (response);
271} 269}
272 270
273 271
274void 272void
275MHD_increment_response_rc(struct MHD_Response * response) { 273MHD_increment_response_rc (struct MHD_Response *response)
276 pthread_mutex_lock(&response->mutex); 274{
275 pthread_mutex_lock (&response->mutex);
277 response->reference_count++; 276 response->reference_count++;
278 pthread_mutex_unlock(&response->mutex); 277 pthread_mutex_unlock (&response->mutex);
279} 278}
280 279
281 280
diff --git a/src/daemon/response.h b/src/daemon/response.h
index ab582f00..a31ba30f 100644
--- a/src/daemon/response.h
+++ b/src/daemon/response.h
@@ -32,7 +32,7 @@
32 * Increment response RC. Should this be part of the 32 * Increment response RC. Should this be part of the
33 * public API? 33 * public API?
34 */ 34 */
35void MHD_increment_response_rc(struct MHD_Response * response); 35void MHD_increment_response_rc (struct MHD_Response *response);
36 36
37 37
38#endif 38#endif
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index e678d4b1..eb96e807 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -52,8 +52,9 @@
52#endif 52#endif
53 53
54#ifdef __cplusplus 54#ifdef __cplusplus
55extern "C" { 55extern "C"
56#if 0 /* keep Emacsens' auto-indent happy */ 56{
57#if 0 /* keep Emacsens' auto-indent happy */
57} 58}
58#endif 59#endif
59#endif 60#endif
@@ -216,7 +217,8 @@ extern "C" {
216 * implemented or not supported on the target platform (i.e. no 217 * implemented or not supported on the target platform (i.e. no
217 * support for SSL, threads or IPv6). 218 * support for SSL, threads or IPv6).
218 */ 219 */
219enum MHD_FLAG { 220enum MHD_FLAG
221{
220 /** 222 /**
221 * No options selected. 223 * No options selected.
222 */ 224 */
@@ -256,7 +258,8 @@ enum MHD_FLAG {
256 * MHD options. Passed in the varargs portion 258 * MHD options. Passed in the varargs portion
257 * of MHD_start_daemon. 259 * of MHD_start_daemon.
258 */ 260 */
259enum MHD_OPTION { 261enum MHD_OPTION
262{
260 263
261 /** 264 /**
262 * No more options / last option. This is used 265 * No more options / last option. This is used
@@ -282,7 +285,8 @@ enum MHD_OPTION {
282 * The MHD_ValueKind specifies the source of 285 * The MHD_ValueKind specifies the source of
283 * the key-value pairs in the HTTP protocol. 286 * the key-value pairs in the HTTP protocol.
284 */ 287 */
285enum MHD_ValueKind { 288enum MHD_ValueKind
289{
286 290
287 /** 291 /**
288 * Response header 292 * Response header
@@ -344,9 +348,9 @@ struct MHD_Response;
344 * @return MHD_YES if connection is allowed, MHD_NO if not 348 * @return MHD_YES if connection is allowed, MHD_NO if not
345 */ 349 */
346typedef int 350typedef int
347(*MHD_AcceptPolicyCallback)(void * cls, 351 (*MHD_AcceptPolicyCallback) (void *cls,
348 const struct sockaddr * addr, 352 const struct sockaddr * addr,
349 socklen_t addrlen); 353 socklen_t addrlen);
350 354
351/** 355/**
352 * A client has requested the given url using the given method ("GET", 356 * A client has requested the given url using the given method ("GET",
@@ -372,13 +376,13 @@ typedef int
372 * error while handling the request 376 * error while handling the request
373 */ 377 */
374typedef int 378typedef int
375(*MHD_AccessHandlerCallback)(void * cls, 379 (*MHD_AccessHandlerCallback) (void *cls,
376 struct MHD_Connection * connection, 380 struct MHD_Connection * connection,
377 const char * url, 381 const char *url,
378 const char * method, 382 const char *method,
379 const char * version, 383 const char *version,
380 const char * upload_data, 384 const char *upload_data,
381 unsigned int * upload_data_size); 385 unsigned int *upload_data_size);
382 386
383/** 387/**
384 * Iterator over key-value pairs. This iterator 388 * Iterator over key-value pairs. This iterator
@@ -391,10 +395,9 @@ typedef int
391 * MHD_NO to abort the iteration 395 * MHD_NO to abort the iteration
392 */ 396 */
393typedef int 397typedef int
394(*MHD_KeyValueIterator)(void * cls, 398 (*MHD_KeyValueIterator) (void *cls,
395 enum MHD_ValueKind kind, 399 enum MHD_ValueKind kind,
396 const char * key, 400 const char *key, const char *value);
397 const char * value);
398 401
399/** 402/**
400 * Callback used by libmicrohttpd in order to obtain content. The 403 * Callback used by libmicrohttpd in order to obtain content. The
@@ -423,10 +426,7 @@ typedef int
423 * with the client). 426 * with the client).
424 */ 427 */
425typedef int 428typedef int
426(*MHD_ContentReaderCallback)(void * cls, 429 (*MHD_ContentReaderCallback) (void *cls, size_t pos, char *buf, int max);
427 size_t pos,
428 char * buf,
429 int max);
430 430
431/** 431/**
432 * This method is called by libmicrohttpd if we 432 * This method is called by libmicrohttpd if we
@@ -434,8 +434,7 @@ typedef int
434 * be used to free resources associated with the 434 * be used to free resources associated with the
435 * content reader. 435 * content reader.
436 */ 436 */
437typedef void 437typedef void (*MHD_ContentReaderFreeCallback) (void *cls);
438(*MHD_ContentReaderFreeCallback)(void * cls);
439 438
440/** 439/**
441 * Start a webserver on the given port. 440 * Start a webserver on the given port.
@@ -452,22 +451,19 @@ typedef void
452 * terminated with MHD_OPTION_END). 451 * terminated with MHD_OPTION_END).
453 * @return NULL on error, handle to daemon on success 452 * @return NULL on error, handle to daemon on success
454 */ 453 */
455struct MHD_Daemon * 454struct MHD_Daemon *MHD_start_daemon (unsigned int flags,
456MHD_start_daemon(unsigned int flags, 455 unsigned short port,
457 unsigned short port, 456 MHD_AcceptPolicyCallback apc,
458 MHD_AcceptPolicyCallback apc, 457 void *apc_cls,
459 void * apc_cls, 458 MHD_AccessHandlerCallback dh,
460 MHD_AccessHandlerCallback dh, 459 void *dh_cls, ...);
461 void * dh_cls,
462 ...);
463 460
464 461
465 462
466/** 463/**
467 * Shutdown an http daemon. 464 * Shutdown an http daemon.
468 */ 465 */
469void 466void MHD_stop_daemon (struct MHD_Daemon *daemon);
470MHD_stop_daemon(struct MHD_Daemon * daemon);
471 467
472 468
473/** 469/**
@@ -478,11 +474,9 @@ MHD_stop_daemon(struct MHD_Daemon * daemon);
478 * options for this call. 474 * options for this call.
479 */ 475 */
480int 476int
481MHD_get_fdset(struct MHD_Daemon * daemon, 477MHD_get_fdset (struct MHD_Daemon *daemon,
482 fd_set * read_fd_set, 478 fd_set * read_fd_set,
483 fd_set * write_fd_set, 479 fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd);
484 fd_set * except_fd_set,
485 int * max_fd);
486 480
487/** 481/**
488 * Run webserver operations (without blocking unless 482 * Run webserver operations (without blocking unless
@@ -494,8 +488,7 @@ MHD_get_fdset(struct MHD_Daemon * daemon,
494 * daemon was not started with the right 488 * daemon was not started with the right
495 * options for this call. 489 * options for this call.
496 */ 490 */
497int 491int MHD_run (struct MHD_Daemon *daemon);
498MHD_run(struct MHD_Daemon * daemon);
499 492
500 493
501/** 494/**
@@ -506,10 +499,9 @@ MHD_run(struct MHD_Daemon * daemon);
506 * already exists 499 * already exists
507 */ 500 */
508int 501int
509MHD_register_handler(struct MHD_Daemon * daemon, 502MHD_register_handler (struct MHD_Daemon *daemon,
510 const char * uri_prefix, 503 const char *uri_prefix,
511 MHD_AccessHandlerCallback dh, 504 MHD_AccessHandlerCallback dh, void *dh_cls);
512 void * dh_cls);
513 505
514/** 506/**
515 * Unregister an access handler for the URIs beginning with 507 * Unregister an access handler for the URIs beginning with
@@ -520,10 +512,9 @@ MHD_register_handler(struct MHD_Daemon * daemon,
520 * is not known for this daemon 512 * is not known for this daemon
521 */ 513 */
522int 514int
523MHD_unregister_handler(struct MHD_Daemon * daemon, 515MHD_unregister_handler (struct MHD_Daemon *daemon,
524 const char * uri_prefix, 516 const char *uri_prefix,
525 MHD_AccessHandlerCallback dh, 517 MHD_AccessHandlerCallback dh, void *dh_cls);
526 void * dh_cls);
527 518
528/** 519/**
529 * Get all of the headers from the request. 520 * Get all of the headers from the request.
@@ -534,10 +525,9 @@ MHD_unregister_handler(struct MHD_Daemon * daemon,
534 * @return number of entries iterated over 525 * @return number of entries iterated over
535 */ 526 */
536int 527int
537MHD_get_connection_values(struct MHD_Connection * connection, 528MHD_get_connection_values (struct MHD_Connection *connection,
538 enum MHD_ValueKind kind, 529 enum MHD_ValueKind kind,
539 MHD_KeyValueIterator iterator, 530 MHD_KeyValueIterator iterator, void *iterator_cls);
540 void * iterator_cls);
541 531
542/** 532/**
543 * Get a particular header value. If multiple 533 * Get a particular header value. If multiple
@@ -546,10 +536,9 @@ MHD_get_connection_values(struct MHD_Connection * connection,
546 * @param key the header to look for 536 * @param key the header to look for
547 * @return NULL if no such item was found 537 * @return NULL if no such item was found
548 */ 538 */
549const char * 539const char *MHD_lookup_connection_value (struct MHD_Connection *connection,
550MHD_lookup_connection_value(struct MHD_Connection * connection, 540 enum MHD_ValueKind kind,
551 enum MHD_ValueKind kind, 541 const char *key);
552 const char * key);
553 542
554/** 543/**
555 * Queue a response to be transmitted to the client (as soon as 544 * Queue a response to be transmitted to the client (as soon as
@@ -562,11 +551,10 @@ MHD_lookup_connection_value(struct MHD_Connection * connection,
562 * MHD_YES on success or if message has been queued 551 * MHD_YES on success or if message has been queued
563 */ 552 */
564int 553int
565MHD_queue_response(struct MHD_Connection * connection, 554MHD_queue_response (struct MHD_Connection *connection,
566 unsigned int status_code, 555 unsigned int status_code, struct MHD_Response *response);
567 struct MHD_Response * response); 556
568 557
569
570/** 558/**
571 * Create a response object. The response object can be extended with 559 * Create a response object. The response object can be extended with
572 * header information and then be used any number of times. 560 * header information and then be used any number of times.
@@ -577,11 +565,11 @@ MHD_queue_response(struct MHD_Connection * connection,
577 * @param crfc callback to call to free crc_cls resources 565 * @param crfc callback to call to free crc_cls resources
578 * @return NULL on error (i.e. invalid arguments, out of memory) 566 * @return NULL on error (i.e. invalid arguments, out of memory)
579 */ 567 */
580struct MHD_Response * 568struct MHD_Response *MHD_create_response_from_callback (size_t size,
581MHD_create_response_from_callback(size_t size, 569 MHD_ContentReaderCallback
582 MHD_ContentReaderCallback crc, 570 crc, void *crc_cls,
583 void * crc_cls, 571 MHD_ContentReaderFreeCallback
584 MHD_ContentReaderFreeCallback crfc); 572 crfc);
585 573
586/** 574/**
587 * Create a response object. The response object can be extended with 575 * Create a response object. The response object can be extended with
@@ -595,11 +583,10 @@ MHD_create_response_from_callback(size_t size,
595 * this call returns 583 * this call returns
596 * @return NULL on error (i.e. invalid arguments, out of memory) 584 * @return NULL on error (i.e. invalid arguments, out of memory)
597 */ 585 */
598struct MHD_Response * 586struct MHD_Response *MHD_create_response_from_data (size_t size,
599MHD_create_response_from_data(size_t size, 587 void *data,
600 void * data, 588 int must_free,
601 int must_free, 589 int must_copy);
602 int must_copy);
603 590
604/** 591/**
605 * Destroy a response object and associated resources. Note that 592 * Destroy a response object and associated resources. Note that
@@ -607,8 +594,7 @@ MHD_create_response_from_data(size_t size,
607 * is still in the queue for some clients, so the memory may not 594 * is still in the queue for some clients, so the memory may not
608 * necessarily be freed immediatley. 595 * necessarily be freed immediatley.
609 */ 596 */
610void 597void MHD_destroy_response (struct MHD_Response *response);
611MHD_destroy_response(struct MHD_Response * response);
612 598
613/** 599/**
614 * Add a header line to the response. 600 * Add a header line to the response.
@@ -616,9 +602,8 @@ MHD_destroy_response(struct MHD_Response * response);
616 * @return MHD_NO on error (i.e. invalid header or content format). 602 * @return MHD_NO on error (i.e. invalid header or content format).
617 */ 603 */
618int 604int
619MHD_add_response_header(struct MHD_Response * response, 605MHD_add_response_header (struct MHD_Response *response,
620 const char * header, 606 const char *header, const char *content);
621 const char * content);
622 607
623/** 608/**
624 * Delete a header line from the response. 609 * Delete a header line from the response.
@@ -626,9 +611,8 @@ MHD_add_response_header(struct MHD_Response * response,
626 * @return MHD_NO on error (no such header known) 611 * @return MHD_NO on error (no such header known)
627 */ 612 */
628int 613int
629MHD_del_response_header(struct MHD_Response * response, 614MHD_del_response_header (struct MHD_Response *response,
630 const char * header, 615 const char *header, const char *content);
631 const char * content);
632 616
633/** 617/**
634 * Get all of the headers added to a response. 618 * Get all of the headers added to a response.
@@ -639,9 +623,8 @@ MHD_del_response_header(struct MHD_Response * response,
639 * @return number of entries iterated over 623 * @return number of entries iterated over
640 */ 624 */
641int 625int
642MHD_get_response_headers(struct MHD_Response * response, 626MHD_get_response_headers (struct MHD_Response *response,
643 MHD_KeyValueIterator iterator, 627 MHD_KeyValueIterator iterator, void *iterator_cls);
644 void * iterator_cls);
645 628
646 629
647/** 630/**
@@ -650,12 +633,11 @@ MHD_get_response_headers(struct MHD_Response * response,
650 * @param key which header to get 633 * @param key which header to get
651 * @return NULL if header does not exist 634 * @return NULL if header does not exist
652 */ 635 */
653const char * 636const char *MHD_get_response_header (struct MHD_Response *response,
654MHD_get_response_header(struct MHD_Response * response, 637 const char *key);
655 const char * key);
656 638
657 639
658#if 0 /* keep Emacsens' auto-indent happy */ 640#if 0 /* keep Emacsens' auto-indent happy */
659{ 641{
660#endif 642#endif
661#ifdef __cplusplus 643#ifdef __cplusplus