aboutsummaryrefslogtreecommitdiff
path: root/src/testcurl/test_quiesce_stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testcurl/test_quiesce_stream.c')
-rw-r--r--src/testcurl/test_quiesce_stream.c207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/testcurl/test_quiesce_stream.c b/src/testcurl/test_quiesce_stream.c
new file mode 100644
index 00000000..478b1109
--- /dev/null
+++ b/src/testcurl/test_quiesce_stream.c
@@ -0,0 +1,207 @@
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2016 Christian Grothoff
4
5 libmicrohttpd is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 libmicrohttpd is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with libmicrohttpd; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file test_quiesce_stream.c
22 * @brief Testcase for libmicrohttpd quiescing
23 * @author Markus Doppelbauer
24 * @author Christian Grothoff
25 */
26#include <stdlib.h>
27#include <stdio.h>
28#include <string.h>
29#include <errno.h>
30#include <arpa/inet.h>
31#include <unistd.h>
32#include <fcntl.h>
33#include <pthread.h>
34#include <microhttpd.h>
35
36
37static volatile unsigned int request_counter;
38
39
40static void
41http_PanicCallback (void *cls,
42 const char *file,
43 unsigned int line,
44 const char *reason)
45{
46 fprintf( stderr,
47 "PANIC: exit process: %s at %s:%u\n",
48 reason,
49 file,
50 line);
51 exit (EXIT_FAILURE);
52}
53
54
55static void *
56resume_connection (void *arg)
57{
58 struct MHD_Connection *connection = arg;
59
60 MHD_resume_connection (connection);
61 return NULL;
62}
63
64
65static void
66suspend_connection (struct MHD_Connection *connection)
67{
68 pthread_t thread_id;
69
70 MHD_suspend_connection (connection);
71 int status = pthread_create (&thread_id,
72 NULL,
73 &resume_connection,
74 connection);
75 if (0 != status)
76 {
77 fprintf (stderr,
78 "Could not create thead\n");
79 exit( EXIT_FAILURE );
80 }
81 pthread_detach (thread_id);
82}
83
84
85struct ContentReaderUserdata
86{
87 int bytes_written;
88 struct MHD_Connection *connection;
89};
90
91
92static ssize_t
93http_ContentReaderCallback (void *cls,
94 uint64_t pos,
95 char *buf,
96 size_t max)
97{
98 static const char alphabet[] = "\nABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
99 struct ContentReaderUserdata *userdata = cls;
100
101 if( userdata->bytes_written >= 1024)
102 {
103 fprintf( stderr,
104 "finish: %d\n",
105 request_counter);
106 return MHD_CONTENT_READER_END_OF_STREAM;
107 }
108 userdata->bytes_written++;
109 buf[0] = alphabet[userdata->bytes_written % (sizeof(alphabet) - 1)];
110 suspend_connection (userdata->connection);
111
112 return 1;
113}
114
115
116static int
117http_AccessHandlerCallback (void *cls,
118 struct MHD_Connection *connection,
119 const char *url,
120 const char *method,
121 const char *version,
122 const char *upload_data,
123 size_t *upload_data_size,
124 void **con_cls )
125{
126 int ret;
127
128 /* Never respond on first call */
129 if (NULL == *con_cls)
130 {
131 fprintf (stderr,
132 "start: %d\n",
133 ++request_counter);
134
135 struct ContentReaderUserdata *userdata = malloc (sizeof(struct ContentReaderUserdata));
136
137 if (NULL == userdata)
138 return MHD_NO;
139 userdata->bytes_written = 0;
140 userdata->connection = connection;
141 *con_cls = userdata;
142 return MHD_YES;
143 }
144
145 /* Second call: create response */
146 struct MHD_Response *response
147 = MHD_create_response_from_callback (-1,
148 32 * 1024,
149 &http_ContentReaderCallback,
150 *con_cls,
151 NULL);
152 ret = MHD_queue_response (connection,
153 MHD_HTTP_OK,
154 response);
155 MHD_destroy_response (response);
156
157 suspend_connection (connection);
158 return ret;
159}
160
161
162int
163main()
164{
165 // Panic callback
166 MHD_set_panic_func (&http_PanicCallback,
167 NULL);
168
169 // Flags
170 unsigned int daemon_flags
171 = MHD_USE_SELECT_INTERNALLY
172 | MHD_USE_EPOLL
173 | MHD_USE_SUSPEND_RESUME
174 | MHD_USE_PIPE_FOR_SHUTDOWN;
175
176 // Create daemon
177 struct MHD_Daemon *daemon = MHD_start_daemon (daemon_flags,
178 8000,
179 NULL,
180 NULL,
181 &http_AccessHandlerCallback,
182 NULL,
183 MHD_OPTION_END);
184 if (NULL == daemon)
185 return EXIT_FAILURE;
186 if (0 != system ("wget --server-response -q -O - 127.0.0.1:8000"))
187 {
188 MHD_stop_daemon (daemon);
189 return EXIT_SUCCESS;
190 }
191 // wait for a request
192 while (0 == request_counter)
193 sleep (1);
194
195 fprintf (stderr,
196 "quiesce\n");
197 MHD_quiesce_daemon (daemon);
198
199 /* wait a second */
200 sleep (1);
201
202 fprintf (stderr,
203 "stopping daemon\n");
204 MHD_stop_daemon (daemon);
205
206 return EXIT_SUCCESS;
207}