diff options
Diffstat (limited to 'src/microhttpd/connection.c')
-rw-r--r-- | src/microhttpd/connection.c | 139 |
1 files changed, 96 insertions, 43 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index a16bf62d..de67f800 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of libmicrohttpd | 2 | This file is part of libmicrohttpd |
3 | (C) 2007, 2008, 2009, 2010, 2011, 2012 Daniel Pittman and Christian Grothoff | 3 | (C) 2007-2013 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 |
@@ -266,8 +266,9 @@ MHD_connection_close (struct MHD_Connection *connection, | |||
266 | struct MHD_Daemon *daemon; | 266 | struct MHD_Daemon *daemon; |
267 | 267 | ||
268 | daemon = connection->daemon; | 268 | daemon = connection->daemon; |
269 | SHUTDOWN (connection->socket_fd, | 269 | if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO)) |
270 | (MHD_YES == connection->read_closed) ? SHUT_WR : SHUT_RDWR); | 270 | SHUTDOWN (connection->socket_fd, |
271 | (MHD_YES == connection->read_closed) ? SHUT_WR : SHUT_RDWR); | ||
271 | connection->state = MHD_CONNECTION_CLOSED; | 272 | connection->state = MHD_CONNECTION_CLOSED; |
272 | connection->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP; | 273 | connection->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP; |
273 | if ( (NULL != daemon->notify_completed) && | 274 | if ( (NULL != daemon->notify_completed) && |
@@ -1485,7 +1486,7 @@ do_read (struct MHD_Connection *connection) | |||
1485 | if (bytes_read < 0) | 1486 | if (bytes_read < 0) |
1486 | { | 1487 | { |
1487 | if ((EINTR == errno) || (EAGAIN == errno)) | 1488 | if ((EINTR == errno) || (EAGAIN == errno)) |
1488 | return MHD_NO; | 1489 | return MHD_NO; |
1489 | #if HAVE_MESSAGES | 1490 | #if HAVE_MESSAGES |
1490 | #if HTTPS_SUPPORT | 1491 | #if HTTPS_SUPPORT |
1491 | if (0 != (connection->daemon->options & MHD_USE_SSL)) | 1492 | if (0 != (connection->daemon->options & MHD_USE_SSL)) |
@@ -2032,6 +2033,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
2032 | int rend; | 2033 | int rend; |
2033 | char *line; | 2034 | char *line; |
2034 | 2035 | ||
2036 | connection->in_idle = MHD_YES; | ||
2035 | while (1) | 2037 | while (1) |
2036 | { | 2038 | { |
2037 | #if DEBUG_STATES | 2039 | #if DEBUG_STATES |
@@ -2376,32 +2378,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
2376 | } | 2378 | } |
2377 | continue; | 2379 | continue; |
2378 | case MHD_CONNECTION_CLOSED: | 2380 | case MHD_CONNECTION_CLOSED: |
2379 | if (connection->response != NULL) | 2381 | goto cleanup_connection; |
2380 | { | ||
2381 | MHD_destroy_response (connection->response); | ||
2382 | connection->response = NULL; | ||
2383 | } | ||
2384 | if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && | ||
2385 | (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) ) | ||
2386 | MHD_PANIC ("Failed to acquire cleanup mutex\n"); | ||
2387 | if (connection->connection_timeout == daemon->connection_timeout) | ||
2388 | XDLL_remove (daemon->normal_timeout_head, | ||
2389 | daemon->normal_timeout_tail, | ||
2390 | connection); | ||
2391 | else | ||
2392 | XDLL_remove (daemon->manual_timeout_head, | ||
2393 | daemon->manual_timeout_tail, | ||
2394 | connection); | ||
2395 | DLL_remove (daemon->connections_head, | ||
2396 | daemon->connections_tail, | ||
2397 | connection); | ||
2398 | DLL_insert (daemon->cleanup_head, | ||
2399 | daemon->cleanup_tail, | ||
2400 | connection); | ||
2401 | if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && | ||
2402 | (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex)) ) | ||
2403 | MHD_PANIC ("Failed to release cleanup mutex\n"); | ||
2404 | return MHD_NO; | ||
2405 | default: | 2382 | default: |
2406 | EXTRA_CHECK (0); | 2383 | EXTRA_CHECK (0); |
2407 | break; | 2384 | break; |
@@ -2413,35 +2390,109 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
2413 | (timeout <= (MHD_monotonic_time() - connection->last_activity)) ) | 2390 | (timeout <= (MHD_monotonic_time() - connection->last_activity)) ) |
2414 | { | 2391 | { |
2415 | MHD_connection_close (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); | 2392 | MHD_connection_close (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); |
2393 | connection->in_idle = MHD_NO; | ||
2416 | return MHD_YES; | 2394 | return MHD_YES; |
2417 | } | 2395 | } |
2418 | MHD_connection_update_event_loop_info (connection); | 2396 | MHD_connection_update_event_loop_info (connection); |
2419 | switch (connection->event_loop_info) | 2397 | switch (connection->event_loop_info) |
2420 | { | 2398 | { |
2421 | case MHD_EVENT_LOOP_INFO_READ: | 2399 | case MHD_EVENT_LOOP_INFO_READ: |
2422 | if (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) | 2400 | if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) && |
2423 | EDLL_insert (daemon->eready_head, | 2401 | (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) ) |
2424 | daemon->eready_tail, | 2402 | { |
2425 | connection); | 2403 | EDLL_insert (daemon->eready_head, |
2404 | daemon->eready_tail, | ||
2405 | connection); | ||
2406 | connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; | ||
2407 | } | ||
2426 | break; | 2408 | break; |
2427 | case MHD_EVENT_LOOP_INFO_WRITE: | 2409 | case MHD_EVENT_LOOP_INFO_WRITE: |
2428 | if (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) | 2410 | if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) && |
2429 | EDLL_insert (daemon->eready_head, | 2411 | (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) ) |
2430 | daemon->eready_tail, | 2412 | { |
2431 | connection); | 2413 | EDLL_insert (daemon->eready_head, |
2414 | daemon->eready_tail, | ||
2415 | connection); | ||
2416 | connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; | ||
2417 | } | ||
2432 | break; | 2418 | break; |
2433 | case MHD_EVENT_LOOP_INFO_BLOCK: | 2419 | case MHD_EVENT_LOOP_INFO_BLOCK: |
2434 | /* we should look at this connection again in the next iteration | 2420 | /* we should look at this connection again in the next iteration |
2435 | of the event loop, as we're waiting on the application */ | 2421 | of the event loop, as we're waiting on the application */ |
2436 | EDLL_insert (daemon->eready_head, | 2422 | if (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) |
2437 | daemon->eready_tail, | 2423 | { |
2438 | connection); | 2424 | EDLL_insert (daemon->eready_head, |
2425 | daemon->eready_tail, | ||
2426 | connection); | ||
2427 | connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; | ||
2428 | } | ||
2439 | break; | 2429 | break; |
2440 | case MHD_EVENT_LOOP_INFO_CLEANUP: | 2430 | case MHD_EVENT_LOOP_INFO_CLEANUP: |
2441 | /* This connection is finished, nothing left to do */ | 2431 | /* This connection is finished, nothing left to do */ |
2442 | break; | 2432 | break; |
2443 | } | 2433 | } |
2434 | |||
2435 | #if EPOLL_SUPPORT | ||
2436 | if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) && | ||
2437 | (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) && | ||
2438 | ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) || | ||
2439 | ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) && | ||
2440 | (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) && | ||
2441 | (MHD_NO == connection->read_closed) ) ) ) | ||
2442 | { | ||
2443 | /* add to epoll set */ | ||
2444 | struct epoll_event event; | ||
2445 | |||
2446 | event.events = EPOLLIN | EPOLLOUT | EPOLLET; | ||
2447 | event.data.ptr = connection; | ||
2448 | if (0 != epoll_ctl (daemon->epoll_fd, | ||
2449 | EPOLL_CTL_ADD, | ||
2450 | connection->socket_fd, | ||
2451 | &event)) | ||
2452 | { | ||
2453 | #if HAVE_MESSAGES | ||
2454 | if (0 != (daemon->options & MHD_USE_DEBUG)) | ||
2455 | MHD_DLOG (daemon, | ||
2456 | "Call to epoll_ctl failed: %s\n", | ||
2457 | STRERROR (errno)); | ||
2458 | #endif | ||
2459 | connection->state = MHD_CONNECTION_CLOSED; | ||
2460 | goto cleanup_connection; | ||
2461 | } | ||
2462 | connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET; | ||
2463 | } | ||
2464 | #endif | ||
2465 | connection->in_idle = MHD_NO; | ||
2444 | return MHD_YES; | 2466 | return MHD_YES; |
2467 | |||
2468 | cleanup_connection: | ||
2469 | if (NULL != connection->response) | ||
2470 | { | ||
2471 | MHD_destroy_response (connection->response); | ||
2472 | connection->response = NULL; | ||
2473 | } | ||
2474 | if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && | ||
2475 | (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) ) | ||
2476 | MHD_PANIC ("Failed to acquire cleanup mutex\n"); | ||
2477 | if (connection->connection_timeout == daemon->connection_timeout) | ||
2478 | XDLL_remove (daemon->normal_timeout_head, | ||
2479 | daemon->normal_timeout_tail, | ||
2480 | connection); | ||
2481 | else | ||
2482 | XDLL_remove (daemon->manual_timeout_head, | ||
2483 | daemon->manual_timeout_tail, | ||
2484 | connection); | ||
2485 | DLL_remove (daemon->connections_head, | ||
2486 | daemon->connections_tail, | ||
2487 | connection); | ||
2488 | DLL_insert (daemon->cleanup_head, | ||
2489 | daemon->cleanup_tail, | ||
2490 | connection); | ||
2491 | if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && | ||
2492 | (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex)) ) | ||
2493 | MHD_PANIC ("Failed to release cleanup mutex\n"); | ||
2494 | connection->in_idle = MHD_NO; | ||
2495 | return MHD_NO; | ||
2445 | } | 2496 | } |
2446 | 2497 | ||
2447 | 2498 | ||
@@ -2589,11 +2640,13 @@ MHD_queue_response (struct MHD_Connection *connection, | |||
2589 | /* response was queued "early", | 2640 | /* response was queued "early", |
2590 | refuse to read body / footers or further | 2641 | refuse to read body / footers or further |
2591 | requests! */ | 2642 | requests! */ |
2592 | (void) SHUTDOWN (connection->socket_fd, SHUT_RD); | 2643 | if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO)) |
2644 | (void) SHUTDOWN (connection->socket_fd, SHUT_RD); | ||
2593 | connection->read_closed = MHD_YES; | 2645 | connection->read_closed = MHD_YES; |
2594 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; | 2646 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; |
2595 | } | 2647 | } |
2596 | (void) MHD_connection_handle_idle (connection); | 2648 | if (MHD_NO == connection->in_idle) |
2649 | (void) MHD_connection_handle_idle (connection); | ||
2597 | return MHD_YES; | 2650 | return MHD_YES; |
2598 | } | 2651 | } |
2599 | 2652 | ||