aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-02-16 07:13:34 +0100
committerChristian Grothoff <christian@grothoff.org>2018-02-16 07:13:34 +0100
commite101aeb4a9e18d506bd93afc87ea55183128f2cd (patch)
treed1d53999712b238dfa6cd3d2ddbaf42d74b51c04 /src
parenta104a2a46a8d3ef1787f7171295af3acc63c4912 (diff)
downloadlibmicrohttpd-e101aeb4a9e18d506bd93afc87ea55183128f2cd.tar.gz
libmicrohttpd-e101aeb4a9e18d506bd93afc87ea55183128f2cd.zip
implement connection_cleanup.c
Diffstat (limited to 'src')
-rw-r--r--src/include/microhttpd_tls.h1
-rw-r--r--src/lib/Makefile.am1
-rw-r--r--src/lib/connection_cleanup.c158
-rw-r--r--src/lib/connection_cleanup.h42
-rw-r--r--src/lib/daemon_close_all_connections.c8
-rw-r--r--src/lib/daemon_destroy.c1
-rw-r--r--src/lib/daemon_epoll.c2
-rw-r--r--src/lib/daemon_info.c3
-rw-r--r--src/lib/daemon_run.c7
-rw-r--r--src/lib/daemon_select.c11
-rw-r--r--src/lib/daemon_start.c5
-rw-r--r--src/microhttpd/connection_https.c2
12 files changed, 226 insertions, 15 deletions
diff --git a/src/include/microhttpd_tls.h b/src/include/microhttpd_tls.h
index 0a9d1793..cdad0953 100644
--- a/src/include/microhttpd_tls.h
+++ b/src/include/microhttpd_tls.h
@@ -19,6 +19,7 @@
19struct MHD_TLS_ConnectionState; 19struct MHD_TLS_ConnectionState;
20 20
21 21
22
22/** 23/**
23 * Callback functions to use for TLS operations. 24 * Callback functions to use for TLS operations.
24 */ 25 */
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index a811a2fd..3c5b6afd 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -59,6 +59,7 @@ libmicrohttpd_la_SOURCES = \
59 action_process_upload.c \ 59 action_process_upload.c \
60 action_suspend.c \ 60 action_suspend.c \
61 connection_add.c connection_add.h \ 61 connection_add.c connection_add.h \
62 connection_cleanup.c connection_cleanup.h \
62 connection_close.c connection_close.h \ 63 connection_close.c connection_close.h \
63 connection_finish_forward.c connection_finish_forward.h \ 64 connection_finish_forward.c connection_finish_forward.h \
64 connection_info.c \ 65 connection_info.c \
diff --git a/src/lib/connection_cleanup.c b/src/lib/connection_cleanup.c
new file mode 100644
index 00000000..cf0b9d45
--- /dev/null
+++ b/src/lib/connection_cleanup.c
@@ -0,0 +1,158 @@
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
19/**
20 * @file lib/connection_cleanup.c
21 * @brief function to clean up completed connections
22 * @author Christian Grothoff
23 */
24#include "internal.h"
25#include "connection_cleanup.h"
26#include "daemon_ip_limit.h"
27
28
29#ifdef UPGRADE_SUPPORT
30/**
31 * Finally cleanup upgrade-related resources. It should
32 * be called when TLS buffers have been drained and
33 * application signaled MHD by #MHD_UPGRADE_ACTION_CLOSE.
34 *
35 * @param connection handle to the upgraded connection to clean
36 */
37static void
38cleanup_upgraded_connection (struct MHD_Connection *connection)
39{
40 struct MHD_UpgradeResponseHandle *urh = connection->request.urh;
41
42 if (NULL == urh)
43 return;
44#ifdef HTTPS_SUPPORT
45 /* Signal remote client the end of TLS connection by
46 * gracefully closing TLS session. */
47 {
48 struct MHD_TLS_Plugin *tls;
49
50 if (NULL != (tls = connection->daemon->tls_api))
51 (void) tls->shutdown_connection (tls->cls,
52 connection->tls_cs);
53 }
54 if (MHD_INVALID_SOCKET != urh->mhd.socket)
55 MHD_socket_close_chk_ (urh->mhd.socket);
56 if (MHD_INVALID_SOCKET != urh->app.socket)
57 MHD_socket_close_chk_ (urh->app.socket);
58#endif /* HTTPS_SUPPORT */
59 connection->request.urh = NULL;
60 free (urh);
61}
62#endif /* UPGRADE_SUPPORT */
63
64
65/**
66 * Free resources associated with all closed connections. (destroy
67 * responses, free buffers, etc.). All closed connections are kept in
68 * the "cleanup" doubly-linked list.
69 *
70 * @remark To be called only from thread that process daemon's
71 * select()/poll()/etc.
72 *
73 * @param daemon daemon to clean up
74 */
75void
76MHD_connection_cleanup_ (struct MHD_Daemon *daemon)
77{
78 struct MHD_Connection *pos;
79
80 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
81 while (NULL != (pos = daemon->cleanup_tail))
82 {
83 DLL_remove (daemon->cleanup_head,
84 daemon->cleanup_tail,
85 pos);
86 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
87
88 if ( (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_model) &&
89 (! pos->thread_joined) &&
90 (! MHD_join_thread_ (pos->pid.handle)) )
91 MHD_PANIC (_("Failed to join a thread\n"));
92#ifdef UPGRADE_SUPPORT
93 cleanup_upgraded_connection (pos);
94#endif /* UPGRADE_SUPPORT */
95 MHD_pool_destroy (pos->request.pool);
96#ifdef HTTPS_SUPPORT
97 {
98 struct MHD_TLS_Plugin *tls;
99
100 if (NULL != (tls = daemon->tls_api))
101 tls->teardown_connection (tls->cls,
102 pos->tls_cs);
103 }
104#endif /* HTTPS_SUPPORT */
105
106 /* clean up the connection */
107 if (NULL != daemon->notify_connection_cb)
108 daemon->notify_connection_cb (daemon->notify_connection_cb_cls,
109 pos,
110 MHD_CONNECTION_NOTIFY_CLOSED);
111 MHD_ip_limit_del (daemon,
112 (const struct sockaddr *) &pos->addr,
113 pos->addr_len);
114#ifdef EPOLL_SUPPORT
115 if (MHD_ELS_EPOLL == daemon->event_loop_syscall)
116 {
117 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
118 {
119 EDLL_remove (daemon->eready_head,
120 daemon->eready_tail,
121 pos);
122 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
123 }
124 if ( (-1 != daemon->epoll_fd) &&
125 (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
126 {
127 /* epoll documentation suggests that closing a FD
128 automatically removes it from the epoll set; however,
129 this is not true as if we fail to do manually remove it,
130 we are still seeing an event for this fd in epoll,
131 causing grief (use-after-free...) --- at least on my
132 system. */
133 if (0 != epoll_ctl (daemon->epoll_fd,
134 EPOLL_CTL_DEL,
135 pos->socket_fd,
136 NULL))
137 MHD_PANIC (_("Failed to remove FD from epoll set\n"));
138 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
139 }
140 }
141#endif
142 if (NULL != pos->request.response)
143 {
144 MHD_response_queue_for_destroy (pos->request.response);
145 pos->request.response = NULL;
146 }
147 if (MHD_INVALID_SOCKET != pos->socket_fd)
148 MHD_socket_close_chk_ (pos->socket_fd);
149 free (pos);
150
151 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
152 daemon->connections--;
153 daemon->at_limit = false;
154 }
155 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
156}
157
158/* end of connection_cleanup.c */
diff --git a/src/lib/connection_cleanup.h b/src/lib/connection_cleanup.h
new file mode 100644
index 00000000..26fbebaf
--- /dev/null
+++ b/src/lib/connection_cleanup.h
@@ -0,0 +1,42 @@
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
19/**
20 * @file lib/connection_cleanup.h
21 * @brief functions to cleanup completed connection
22 * @author Christian Grothoff
23 */
24#ifndef CONNECTION_CLEANUP_H
25#define CONNECTION_CLEANUP_H
26
27
28/**
29 * Free resources associated with all closed connections. (destroy
30 * responses, free buffers, etc.). All closed connections are kept in
31 * the "cleanup" doubly-linked list.
32 *
33 * @remark To be called only from thread that process daemon's
34 * select()/poll()/etc.
35 *
36 * @param daemon daemon to clean up
37 */
38void
39MHD_connection_cleanup_ (struct MHD_Daemon *daemon)
40 MHD_NONNULL (1);
41
42#endif
diff --git a/src/lib/daemon_close_all_connections.c b/src/lib/daemon_close_all_connections.c
index 0d6dd85d..5f85214c 100644
--- a/src/lib/daemon_close_all_connections.c
+++ b/src/lib/daemon_close_all_connections.c
@@ -23,9 +23,11 @@
23 * @author Christian Grothoff 23 * @author Christian Grothoff
24 */ 24 */
25#include "internal.h" 25#include "internal.h"
26#include "connection_cleanup.h"
26#include "connection_close.h" 27#include "connection_close.h"
27#include "connection_finish_forward.h" 28#include "connection_finish_forward.h"
28#include "daemon_close_all_connections.h" 29#include "daemon_close_all_connections.h"
30#include "request_resume.h"
29#include "upgrade_process.h" 31#include "upgrade_process.h"
30 32
31 33
@@ -120,7 +122,7 @@ MHD_daemon_close_all_connections_ (struct MHD_Daemon *daemon)
120 if (! daemon->disallow_suspend_resume) 122 if (! daemon->disallow_suspend_resume)
121 { 123 {
122 daemon->resuming = true; /* Force check for pending resume. */ 124 daemon->resuming = true; /* Force check for pending resume. */
123 resume_suspended_connections (daemon); 125 MHD_resume_suspended_connections_ (daemon);
124 } 126 }
125 /* first, make sure all threads are aware of shutdown; need to 127 /* first, make sure all threads are aware of shutdown; need to
126 traverse DLLs in peace... */ 128 traverse DLLs in peace... */
@@ -211,7 +213,7 @@ MHD_daemon_close_all_connections_ (struct MHD_Daemon *daemon)
211 if (upg_allowed) 213 if (upg_allowed)
212 { 214 {
213 daemon->resuming = true; /* Force check for pending resume. */ 215 daemon->resuming = true; /* Force check for pending resume. */
214 resume_suspended_connections (daemon); 216 MHD_resume_suspended_connections_ (daemon);
215 } 217 }
216#endif /* UPGRADE_SUPPORT */ 218#endif /* UPGRADE_SUPPORT */
217 219
@@ -223,7 +225,7 @@ MHD_daemon_close_all_connections_ (struct MHD_Daemon *daemon)
223 MHD_PANIC (_("Failed to join a thread\n")); 225 MHD_PANIC (_("Failed to join a thread\n"));
224 close_connection (pos); 226 close_connection (pos);
225 } 227 }
226 MHD_cleanup_connections (daemon); 228 MHD_connection_cleanup_ (daemon);
227} 229}
228 230
229/* end of daemon_close_all_connections.c */ 231/* end of daemon_close_all_connections.c */
diff --git a/src/lib/daemon_destroy.c b/src/lib/daemon_destroy.c
index 054ca188..a236ba8f 100644
--- a/src/lib/daemon_destroy.c
+++ b/src/lib/daemon_destroy.c
@@ -24,6 +24,7 @@
24 */ 24 */
25#include "internal.h" 25#include "internal.h"
26#include "request_resume.h" 26#include "request_resume.h"
27#include "daemon_close_all_connections.h"
27 28
28 29
29/** 30/**
diff --git a/src/lib/daemon_epoll.c b/src/lib/daemon_epoll.c
index 115bb9d0..cc2b68ec 100644
--- a/src/lib/daemon_epoll.c
+++ b/src/lib/daemon_epoll.c
@@ -388,7 +388,7 @@ MHD_daemon_epoll_ (struct MHD_Daemon *daemon,
388 * Do not accept more then 10 connections at once. The rest will 388 * Do not accept more then 10 connections at once. The rest will
389 * be accepted on next turn (level trigger is used for listen 389 * be accepted on next turn (level trigger is used for listen
390 * socket). */ 390 * socket). */
391 while ( (MHD_YES == 391 while ( (MHD_SC_OK ==
392 MHD_accept_connection_ (daemon)) && 392 MHD_accept_connection_ (daemon)) &&
393 (series_length < 10) && 393 (series_length < 10) &&
394 (daemon->connections < daemon->global_connection_limit) && 394 (daemon->connections < daemon->global_connection_limit) &&
diff --git a/src/lib/daemon_info.c b/src/lib/daemon_info.c
index 770f74b9..37208da3 100644
--- a/src/lib/daemon_info.c
+++ b/src/lib/daemon_info.c
@@ -23,6 +23,7 @@
23 * @author Christian Grothoff 23 * @author Christian Grothoff
24 */ 24 */
25#include "internal.h" 25#include "internal.h"
26#include "connection_cleanup.h"
26 27
27 28
28/** 29/**
@@ -69,7 +70,7 @@ MHD_daemon_get_information_sz (struct MHD_Daemon *daemon,
69 { 70 {
70 /* Assumes that MHD_run() in not called in other thread 71 /* Assumes that MHD_run() in not called in other thread
71 (of the application) at the same time. */ 72 (of the application) at the same time. */
72 MHD_cleanup_connections (daemon); 73 MHD_connection_cleanup_ (daemon);
73 return_value->num_connections 74 return_value->num_connections
74 = daemon->connections; 75 = daemon->connections;
75 } 76 }
diff --git a/src/lib/daemon_run.c b/src/lib/daemon_run.c
index d95cff12..c9ed3720 100644
--- a/src/lib/daemon_run.c
+++ b/src/lib/daemon_run.c
@@ -23,6 +23,7 @@
23 * @author Christian Grothoff 23 * @author Christian Grothoff
24 */ 24 */
25#include "internal.h" 25#include "internal.h"
26#include "connection_cleanup.h"
26#include "daemon_epoll.h" 27#include "daemon_epoll.h"
27#include "daemon_poll.h" 28#include "daemon_poll.h"
28#include "daemon_select.h" 29#include "daemon_select.h"
@@ -60,19 +61,19 @@ MHD_daemon_run (struct MHD_Daemon *daemon)
60 case MHD_ELS_POLL: 61 case MHD_ELS_POLL:
61 sc = MHD_daemon_poll_ (daemon, 62 sc = MHD_daemon_poll_ (daemon,
62 MHD_NO); 63 MHD_NO);
63 MHD_cleanup_connections (daemon); 64 MHD_connection_cleanup_ (daemon);
64 return sc; 65 return sc;
65#ifdef EPOLL_SUPPORT 66#ifdef EPOLL_SUPPORT
66 case MHD_ELS_EPOLL: 67 case MHD_ELS_EPOLL:
67 sc = MHD_daemon_epoll_ (daemon, 68 sc = MHD_daemon_epoll_ (daemon,
68 MHD_NO); 69 MHD_NO);
69 MHD_cleanup_connections (daemon); 70 MHD_connection_cleanup_ (daemon);
70 return sc; 71 return sc;
71#endif 72#endif
72 case MHD_ELS_SELECT: 73 case MHD_ELS_SELECT:
73 return MHD_daemon_select_ (daemon, 74 return MHD_daemon_select_ (daemon,
74 MHD_NO); 75 MHD_NO);
75 /* MHD_select does MHD_cleanup_connections already */ 76 /* MHD_select does MHD_connection_cleanup_ already */
76 default: 77 default:
77 return MHD_SC_CONFIGURATION_UNEXPECTED_ELS; 78 return MHD_SC_CONFIGURATION_UNEXPECTED_ELS;
78 } 79 }
diff --git a/src/lib/daemon_select.c b/src/lib/daemon_select.c
index ec4da399..3c0360ba 100644
--- a/src/lib/daemon_select.c
+++ b/src/lib/daemon_select.c
@@ -23,10 +23,13 @@
23 * @author Christian Grothoff 23 * @author Christian Grothoff
24 */ 24 */
25#include "internal.h" 25#include "internal.h"
26#include "connection_add.h"
27#include "connection_cleanup.h"
28#include "connection_finish_forward.h"
26#include "daemon_select.h" 29#include "daemon_select.h"
30#include "daemon_epoll.h"
27#include "request_resume.h" 31#include "request_resume.h"
28#include "upgrade_process.h" 32#include "upgrade_process.h"
29#include "connection_finish_forward.h"
30 33
31 34
32/** 35/**
@@ -476,7 +479,7 @@ internal_run_from_select (struct MHD_Daemon *daemon,
476 } 479 }
477 } 480 }
478#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 481#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
479 MHD_cleanup_connections (daemon); 482 MHD_connection_cleanup_ (daemon);
480 return MHD_SC_OK; 483 return MHD_SC_OK;
481} 484}
482 485
@@ -492,7 +495,6 @@ void
492MHD_daemon_upgrade_connection_with_select_ (struct MHD_Connection *con) 495MHD_daemon_upgrade_connection_with_select_ (struct MHD_Connection *con)
493{ 496{
494 struct MHD_UpgradeResponseHandle *urh = con->request.urh; 497 struct MHD_UpgradeResponseHandle *urh = con->request.urh;
495 struct MHD_Daemon *daemon = con->daemon;
496 498
497 while ( (0 != urh->in_buffer_size) || 499 while ( (0 != urh->in_buffer_size) ||
498 (0 != urh->out_buffer_size) || 500 (0 != urh->out_buffer_size) ||
@@ -613,7 +615,7 @@ MHD_daemon_run_from_select (struct MHD_Daemon *daemon,
613 615
614 sc = MHD_daemon_epoll_ (daemon, 616 sc = MHD_daemon_epoll_ (daemon,
615 MHD_NO); 617 MHD_NO);
616 MHD_cleanup_connections (daemon); 618 MHD_connection_cleanup_ (daemon);
617 return sc; 619 return sc;
618#else /* ! EPOLL_SUPPORT */ 620#else /* ! EPOLL_SUPPORT */
619 return MHD_NO; 621 return MHD_NO;
@@ -651,7 +653,6 @@ MHD_daemon_select_ (struct MHD_Daemon *daemon,
651 struct timeval timeout; 653 struct timeval timeout;
652 struct timeval *tv; 654 struct timeval *tv;
653 MHD_UNSIGNED_LONG_LONG ltimeout; 655 MHD_UNSIGNED_LONG_LONG ltimeout;
654 int err_state;
655 MHD_socket ls; 656 MHD_socket ls;
656 enum MHD_StatusCode sc; 657 enum MHD_StatusCode sc;
657 enum MHD_StatusCode sc2; 658 enum MHD_StatusCode sc2;
diff --git a/src/lib/daemon_start.c b/src/lib/daemon_start.c
index f9838d9f..c6349c6d 100644
--- a/src/lib/daemon_start.c
+++ b/src/lib/daemon_start.c
@@ -23,8 +23,11 @@
23 * @author Christian Grothoff 23 * @author Christian Grothoff
24 */ 24 */
25#include "internal.h" 25#include "internal.h"
26#include "connection_cleanup.h"
26#include "daemon_close_all_connections.h" 27#include "daemon_close_all_connections.h"
27#include "daemon_select.h" 28#include "daemon_select.h"
29#include "daemon_poll.h"
30#include "daemon_epoll.h"
28 31
29 32
30/** 33/**
@@ -635,7 +638,7 @@ MHD_polling_thread (void *cls)
635#endif 638#endif
636 break; 639 break;
637 } 640 }
638 MHD_cleanup_connections (daemon); 641 MHD_connection_cleanup_ (daemon);
639 } 642 }
640 /* Resume any pending for resume connections, join 643 /* Resume any pending for resume connections, join
641 * all connection's threads (if any) and finally cleanup 644 * all connection's threads (if any) and finally cleanup
diff --git a/src/microhttpd/connection_https.c b/src/microhttpd/connection_https.c
index 63623138..5efced33 100644
--- a/src/microhttpd/connection_https.c
+++ b/src/microhttpd/connection_https.c
@@ -207,7 +207,7 @@ MHD_tls_connection_shutdown (struct MHD_Connection *connection)
207 if (MHD_TLS_CONN_WR_CLOSED > connection->tls_state) 207 if (MHD_TLS_CONN_WR_CLOSED > connection->tls_state)
208 { 208 {
209 const int res = 209 const int res =
210 gnutls_bye(connection->tls_session, GNUTLS_SHUT_WR); 210 gnutls_bye (connection->tls_session, GNUTLS_SHUT_WR);
211 if (GNUTLS_E_SUCCESS == res) 211 if (GNUTLS_E_SUCCESS == res)
212 { 212 {
213 connection->tls_state = MHD_TLS_CONN_WR_CLOSED; 213 connection->tls_state = MHD_TLS_CONN_WR_CLOSED;