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];