aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/connection.c')
-rw-r--r--src/microhttpd/connection.c139
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