diff options
Diffstat (limited to 'src/daemon/daemon.c')
-rw-r--r-- | src/daemon/daemon.c | 143 |
1 files changed, 80 insertions, 63 deletions
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index 607f544b..26b13d35 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of libmicrohttpd | 2 | This file is part of libmicrohttpd |
3 | (C) 2007 Daniel Pittman and Christian Grothoff | 3 | (C) 2007 Daniel Pittman and Christian Grothoff |
4 | 4 | ||
5 | This library is free software; you can redistribute it and/or | 5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public | 6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | 7 | License as published by the Free Software Foundation; either |
@@ -64,6 +64,12 @@ MHD_register_handler (struct MHD_Daemon *daemon, | |||
64 | ah = ah->next; | 64 | ah = ah->next; |
65 | } | 65 | } |
66 | ah = malloc (sizeof (struct MHD_Access_Handler)); | 66 | ah = malloc (sizeof (struct MHD_Access_Handler)); |
67 | if (ah == NULL) | ||
68 | { | ||
69 | MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno)); | ||
70 | return MHD_NO; | ||
71 | } | ||
72 | |||
67 | ah->next = daemon->handlers; | 73 | ah->next = daemon->handlers; |
68 | ah->uri_prefix = strdup (uri_prefix); | 74 | ah->uri_prefix = strdup (uri_prefix); |
69 | ah->dh = dh; | 75 | ah->dh = dh; |
@@ -133,7 +139,7 @@ MHD_get_fdset (struct MHD_Daemon *daemon, | |||
133 | (write_fd_set == NULL) || | 139 | (write_fd_set == NULL) || |
134 | (except_fd_set == NULL) || | 140 | (except_fd_set == NULL) || |
135 | (max_fd == NULL) || | 141 | (max_fd == NULL) || |
136 | (fd == -1) || | 142 | (fd == -1) || |
137 | (daemon->shutdown == MHD_YES) || | 143 | (daemon->shutdown == MHD_YES) || |
138 | ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0)) | 144 | ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0)) |
139 | return MHD_NO; | 145 | return MHD_NO; |
@@ -174,11 +180,10 @@ MHD_handle_connection (void *data) | |||
174 | if (con == NULL) | 180 | if (con == NULL) |
175 | abort (); | 181 | abort (); |
176 | timeout = con->daemon->connection_timeout; | 182 | timeout = con->daemon->connection_timeout; |
177 | now = time(NULL); | 183 | now = time (NULL); |
178 | while ( (!con->daemon->shutdown) && | 184 | while ((!con->daemon->shutdown) && |
179 | (con->socket_fd != -1) && | 185 | (con->socket_fd != -1) && |
180 | ( (timeout == 0) || | 186 | ((timeout == 0) || (now - timeout > con->last_activity))) |
181 | (now - timeout > con->last_activity) ) ) | ||
182 | { | 187 | { |
183 | FD_ZERO (&rs); | 188 | FD_ZERO (&rs); |
184 | FD_ZERO (&ws); | 189 | FD_ZERO (&ws); |
@@ -187,16 +192,15 @@ MHD_handle_connection (void *data) | |||
187 | MHD_connection_get_fdset (con, &rs, &ws, &es, &max); | 192 | MHD_connection_get_fdset (con, &rs, &ws, &es, &max); |
188 | tv.tv_usec = 0; | 193 | tv.tv_usec = 0; |
189 | tv.tv_sec = timeout - (now - con->last_activity); | 194 | tv.tv_sec = timeout - (now - con->last_activity); |
190 | num_ready = SELECT (max + 1, | 195 | num_ready = SELECT (max + 1, |
191 | &rs, | 196 | &rs, &ws, &es, (timeout != 0) ? &tv : NULL); |
192 | &ws, | 197 | now = time (NULL); |
193 | &es, | ||
194 | (tv.tv_sec != 0) ? &tv : NULL); | ||
195 | now = time(NULL); | ||
196 | if (num_ready < 0) | 198 | if (num_ready < 0) |
197 | { | 199 | { |
198 | if (errno == EINTR) | 200 | if (errno == EINTR) |
199 | continue; | 201 | continue; |
202 | MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n", | ||
203 | max, STRERROR (errno)); | ||
200 | break; | 204 | break; |
201 | } | 205 | } |
202 | if (((FD_ISSET (con->socket_fd, &rs)) && | 206 | if (((FD_ISSET (con->socket_fd, &rs)) && |
@@ -207,10 +211,10 @@ MHD_handle_connection (void *data) | |||
207 | break; | 211 | break; |
208 | if ((con->headersReceived == 1) && (con->response == NULL)) | 212 | if ((con->headersReceived == 1) && (con->response == NULL)) |
209 | MHD_call_connection_handler (con); | 213 | MHD_call_connection_handler (con); |
210 | if ( (con->socket_fd != -1) && | 214 | if ((con->socket_fd != -1) && |
211 | ( (FD_ISSET (con->socket_fd, &rs)) || | 215 | ((FD_ISSET (con->socket_fd, &rs)) || |
212 | (FD_ISSET (con->socket_fd, &ws)) ) ) | 216 | (FD_ISSET (con->socket_fd, &ws)))) |
213 | con->last_activity = now; | 217 | con->last_activity = now; |
214 | } | 218 | } |
215 | if (con->socket_fd != -1) | 219 | if (con->socket_fd != -1) |
216 | { | 220 | { |
@@ -251,6 +255,8 @@ MHD_accept_connection (struct MHD_Daemon *daemon) | |||
251 | if (daemon->max_connections == 0) | 255 | if (daemon->max_connections == 0) |
252 | { | 256 | { |
253 | /* above connection limit - reject */ | 257 | /* above connection limit - reject */ |
258 | MHD_DLOG (daemon, | ||
259 | "Server reached connection limit (closing inbound connection)\n"); | ||
254 | CLOSE (s); | 260 | CLOSE (s); |
255 | return MHD_NO; | 261 | return MHD_NO; |
256 | } | 262 | } |
@@ -261,11 +267,18 @@ MHD_accept_connection (struct MHD_Daemon *daemon) | |||
261 | return MHD_YES; | 267 | return MHD_YES; |
262 | } | 268 | } |
263 | connection = malloc (sizeof (struct MHD_Connection)); | 269 | connection = malloc (sizeof (struct MHD_Connection)); |
270 | if (connection == NULL) | ||
271 | { | ||
272 | MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno)); | ||
273 | CLOSE (s); | ||
274 | return MHD_NO; | ||
275 | } | ||
264 | memset (connection, 0, sizeof (struct MHD_Connection)); | 276 | memset (connection, 0, sizeof (struct MHD_Connection)); |
265 | connection->pool = NULL; | 277 | connection->pool = NULL; |
266 | connection->addr = malloc (addrlen); | 278 | connection->addr = malloc (addrlen); |
267 | if (connection->addr == NULL) | 279 | if (connection->addr == NULL) |
268 | { | 280 | { |
281 | MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno)); | ||
269 | CLOSE (s); | 282 | CLOSE (s); |
270 | free (connection); | 283 | free (connection); |
271 | return MHD_NO; | 284 | return MHD_NO; |
@@ -284,7 +297,7 @@ MHD_accept_connection (struct MHD_Daemon *daemon) | |||
284 | free (connection); | 297 | free (connection); |
285 | return MHD_NO; | 298 | return MHD_NO; |
286 | } | 299 | } |
287 | connection->last_activity = time(NULL); | 300 | connection->last_activity = time (NULL); |
288 | connection->next = daemon->connections; | 301 | connection->next = daemon->connections; |
289 | daemon->connections = connection; | 302 | daemon->connections = connection; |
290 | daemon->max_connections--; | 303 | daemon->max_connections--; |
@@ -310,7 +323,7 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon) | |||
310 | void *unused; | 323 | void *unused; |
311 | time_t timeout; | 324 | time_t timeout; |
312 | 325 | ||
313 | timeout = time(NULL); | 326 | timeout = time (NULL); |
314 | if (daemon->connection_timeout != 0) | 327 | if (daemon->connection_timeout != 0) |
315 | timeout -= daemon->connection_timeout; | 328 | timeout -= daemon->connection_timeout; |
316 | else | 329 | else |
@@ -319,11 +332,11 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon) | |||
319 | prev = NULL; | 332 | prev = NULL; |
320 | while (pos != NULL) | 333 | while (pos != NULL) |
321 | { | 334 | { |
322 | if ( (pos->last_activity < timeout) && | 335 | if ((pos->last_activity < timeout) && (pos->socket_fd != -1)) |
323 | (pos->socket_fd != -1) ) { | 336 | { |
324 | CLOSE(pos->socket_fd); | 337 | CLOSE (pos->socket_fd); |
325 | pos->socket_fd = -1; | 338 | pos->socket_fd = -1; |
326 | } | 339 | } |
327 | if (pos->socket_fd == -1) | 340 | if (pos->socket_fd == -1) |
328 | { | 341 | { |
329 | if (prev == NULL) | 342 | if (prev == NULL) |
@@ -361,33 +374,33 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon) | |||
361 | * (only needed if connection timeout is used). The | 374 | * (only needed if connection timeout is used). The |
362 | * returned value is how long select should at most | 375 | * returned value is how long select should at most |
363 | * block, not the timeout value set for connections. | 376 | * block, not the timeout value set for connections. |
364 | * | 377 | * |
365 | * @param timeout set to the timeout (in milliseconds) | 378 | * @param timeout set to the timeout (in milliseconds) |
366 | * @return MHD_YES on success, MHD_NO if timeouts are | 379 | * @return MHD_YES on success, MHD_NO if timeouts are |
367 | * not used (or no connections exist that would | 380 | * not used (or no connections exist that would |
368 | * necessiate the use of a timeout right now). | 381 | * necessiate the use of a timeout right now). |
369 | */ | 382 | */ |
370 | int | 383 | int |
371 | MHD_get_timeout(struct MHD_Daemon * daemon, | 384 | MHD_get_timeout (struct MHD_Daemon *daemon, unsigned long long *timeout) |
372 | unsigned long long * timeout) { | 385 | { |
373 | time_t earliest_deadline; | 386 | time_t earliest_deadline; |
374 | time_t now; | 387 | time_t now; |
375 | struct MHD_Connection *pos; | 388 | struct MHD_Connection *pos; |
376 | unsigned int dto; | 389 | unsigned int dto; |
377 | 390 | ||
378 | dto = daemon->connection_timeout; | 391 | dto = daemon->connection_timeout; |
379 | if (0 == dto) | 392 | if (0 == dto) |
380 | return MHD_NO; | 393 | return MHD_NO; |
381 | pos = daemon->connections; | 394 | pos = daemon->connections; |
382 | if (pos == NULL) | 395 | if (pos == NULL) |
383 | return MHD_NO; /* no connections */ | 396 | return MHD_NO; /* no connections */ |
384 | now = time(NULL); | 397 | now = time (NULL); |
385 | /* start with conservative estimate */ | 398 | /* start with conservative estimate */ |
386 | earliest_deadline = now + dto; | 399 | earliest_deadline = now + dto; |
387 | while (pos != NULL) | 400 | while (pos != NULL) |
388 | { | 401 | { |
389 | if (earliest_deadline > pos->last_activity + dto) | 402 | if (earliest_deadline > pos->last_activity + dto) |
390 | earliest_deadline = pos->last_activity + dto; | 403 | earliest_deadline = pos->last_activity + dto; |
391 | pos = pos->next; | 404 | pos = pos->next; |
392 | } | 405 | } |
393 | if (earliest_deadline < now) | 406 | if (earliest_deadline < now) |
@@ -419,7 +432,7 @@ MHD_select (struct MHD_Daemon *daemon, int may_block) | |||
419 | 432 | ||
420 | timeout.tv_sec = 0; | 433 | timeout.tv_sec = 0; |
421 | timeout.tv_usec = 0; | 434 | timeout.tv_usec = 0; |
422 | if (daemon == NULL) | 435 | if (daemon == NULL) |
423 | abort (); | 436 | abort (); |
424 | if (daemon->shutdown == MHD_YES) | 437 | if (daemon->shutdown == MHD_YES) |
425 | return MHD_NO; | 438 | return MHD_NO; |
@@ -439,20 +452,24 @@ MHD_select (struct MHD_Daemon *daemon, int may_block) | |||
439 | /* accept only, have one thread per connection */ | 452 | /* accept only, have one thread per connection */ |
440 | max = daemon->socket_fd; | 453 | max = daemon->socket_fd; |
441 | if (max == -1) | 454 | if (max == -1) |
442 | return MHD_NO; | 455 | return MHD_NO; |
443 | FD_SET (max, &rs); | 456 | FD_SET (max, &rs); |
444 | } | 457 | } |
445 | if (may_block == MHD_NO) { | 458 | if (may_block == MHD_NO) |
446 | timeout.tv_usec = 0; | 459 | { |
447 | timeout.tv_sec = 0; | 460 | timeout.tv_usec = 0; |
448 | } else { | 461 | timeout.tv_sec = 0; |
449 | /* ltimeout is in ms */ | 462 | } |
450 | if (MHD_YES == MHD_get_timeout(daemon, <imeout)) { | 463 | else |
451 | timeout.tv_usec = (ltimeout % 1000) * 1000 * 1000; | 464 | { |
452 | timeout.tv_sec = ltimeout / 1000; | 465 | /* ltimeout is in ms */ |
453 | may_block = MHD_NO; | 466 | if (MHD_YES == MHD_get_timeout (daemon, <imeout)) |
454 | } | 467 | { |
455 | } | 468 | timeout.tv_usec = (ltimeout % 1000) * 1000 * 1000; |
469 | timeout.tv_sec = ltimeout / 1000; | ||
470 | may_block = MHD_NO; | ||
471 | } | ||
472 | } | ||
456 | num_ready = SELECT (max + 1, | 473 | num_ready = SELECT (max + 1, |
457 | &rs, &ws, &es, may_block == MHD_NO ? &timeout : NULL); | 474 | &rs, &ws, &es, may_block == MHD_NO ? &timeout : NULL); |
458 | if (daemon->shutdown == MHD_YES) | 475 | if (daemon->shutdown == MHD_YES) |
@@ -472,24 +489,24 @@ MHD_select (struct MHD_Daemon *daemon, int may_block) | |||
472 | if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) | 489 | if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) |
473 | { | 490 | { |
474 | /* do not have a thread per connection, process all connections now */ | 491 | /* do not have a thread per connection, process all connections now */ |
475 | now = time(NULL); | 492 | now = time (NULL); |
476 | pos = daemon->connections; | 493 | pos = daemon->connections; |
477 | while (pos != NULL) | 494 | while (pos != NULL) |
478 | { | 495 | { |
479 | ds = pos->socket_fd; | 496 | ds = pos->socket_fd; |
480 | if (ds == -1) | 497 | if (ds != -1) |
481 | { | 498 | { |
482 | pos = pos->next; | 499 | if (FD_ISSET (ds, &rs)) |
483 | continue; | 500 | { |
501 | pos->last_activity = now; | ||
502 | MHD_connection_handle_read (pos); | ||
503 | } | ||
504 | if (FD_ISSET (ds, &ws)) | ||
505 | { | ||
506 | pos->last_activity = now; | ||
507 | MHD_connection_handle_write (pos); | ||
508 | } | ||
484 | } | 509 | } |
485 | if (FD_ISSET (ds, &rs)) { | ||
486 | pos->last_activity = now; | ||
487 | MHD_connection_handle_read (pos); | ||
488 | } | ||
489 | if (FD_ISSET (ds, &ws)) { | ||
490 | pos->last_activity = now; | ||
491 | MHD_connection_handle_write (pos); | ||
492 | } | ||
493 | pos = pos->next; | 510 | pos = pos->next; |
494 | } | 511 | } |
495 | } | 512 | } |
@@ -629,7 +646,7 @@ MHD_start_daemon (unsigned int options, | |||
629 | retVal->default_handler.next = NULL; | 646 | retVal->default_handler.next = NULL; |
630 | retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT; | 647 | retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT; |
631 | retVal->pool_size = MHD_POOL_SIZE_DEFAULT; | 648 | retVal->pool_size = MHD_POOL_SIZE_DEFAULT; |
632 | retVal->connection_timeout = 0; /* no timeout */ | 649 | retVal->connection_timeout = 0; /* no timeout */ |
633 | va_start (ap, dh_cls); | 650 | va_start (ap, dh_cls); |
634 | while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION))) | 651 | while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION))) |
635 | { | 652 | { |
@@ -641,9 +658,9 @@ MHD_start_daemon (unsigned int options, | |||
641 | case MHD_OPTION_CONNECTION_LIMIT: | 658 | case MHD_OPTION_CONNECTION_LIMIT: |
642 | retVal->max_connections = va_arg (ap, unsigned int); | 659 | retVal->max_connections = va_arg (ap, unsigned int); |
643 | break; | 660 | break; |
644 | case MHD_OPTION_CONNECTION_TIMEOUT: | 661 | case MHD_OPTION_CONNECTION_TIMEOUT: |
645 | retVal->connection_timeout = va_arg (ap, unsigned int); | 662 | retVal->connection_timeout = va_arg (ap, unsigned int); |
646 | break; | 663 | break; |
647 | default: | 664 | default: |
648 | fprintf (stderr, | 665 | fprintf (stderr, |
649 | "Invalid MHD_OPTION argument! (Did you terminate the list with MHD_OPTION_END?)\n"); | 666 | "Invalid MHD_OPTION argument! (Did you terminate the list with MHD_OPTION_END?)\n"); |
@@ -728,12 +745,12 @@ void __attribute__ ((destructor)) MHD_pthread_handlers_ltdl_fini () | |||
728 | #else | 745 | #else |
729 | void __attribute__ ((constructor)) MHD_win_ltdl_init () | 746 | void __attribute__ ((constructor)) MHD_win_ltdl_init () |
730 | { | 747 | { |
731 | plibc_init("CRISP", "libmicrohttpd"); | 748 | plibc_init ("CRISP", "libmicrohttpd"); |
732 | } | 749 | } |
733 | 750 | ||
734 | void __attribute__ ((destructor)) MHD_win_ltdl_fini () | 751 | void __attribute__ ((destructor)) MHD_win_ltdl_fini () |
735 | { | 752 | { |
736 | plibc_shutdown(); | 753 | plibc_shutdown (); |
737 | } | 754 | } |
738 | #endif | 755 | #endif |
739 | 756 | ||