aboutsummaryrefslogtreecommitdiff
path: root/src/daemon/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon/daemon.c')
-rw-r--r--src/daemon/daemon.c143
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 */
370int 383int
371MHD_get_timeout(struct MHD_Daemon * daemon, 384MHD_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, &ltimeout)) { 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, &ltimeout))
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
729void __attribute__ ((constructor)) MHD_win_ltdl_init () 746void __attribute__ ((constructor)) MHD_win_ltdl_init ()
730{ 747{
731 plibc_init("CRISP", "libmicrohttpd"); 748 plibc_init ("CRISP", "libmicrohttpd");
732} 749}
733 750
734void __attribute__ ((destructor)) MHD_win_ltdl_fini () 751void __attribute__ ((destructor)) MHD_win_ltdl_fini ()
735{ 752{
736 plibc_shutdown(); 753 plibc_shutdown ();
737} 754}
738#endif 755#endif
739 756