aboutsummaryrefslogtreecommitdiff
path: root/src/testcurl/https/tls_multi_thread_mode_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testcurl/https/tls_multi_thread_mode_test.c')
-rw-r--r--src/testcurl/https/tls_multi_thread_mode_test.c330
1 files changed, 14 insertions, 316 deletions
diff --git a/src/testcurl/https/tls_multi_thread_mode_test.c b/src/testcurl/https/tls_multi_thread_mode_test.c
index eeb5e8a0..602a7175 100644
--- a/src/testcurl/https/tls_multi_thread_mode_test.c
+++ b/src/testcurl/https/tls_multi_thread_mode_test.c
@@ -35,229 +35,12 @@
35#include "gnutls.h" 35#include "gnutls.h"
36#include <curl/curl.h> 36#include <curl/curl.h>
37 37
38#define DEBUG_CURL_VERBOSE 0 38#include "tls_test_common.h"
39#define PAGE_NOT_FOUND "<html><head><title>File not found</title></head><body>File not found</body></html>" 39extern const char srv_key_pem[];
40 40extern const char srv_self_signed_cert_pem[];
41#define MHD_E_MEM "Error: memory error\n"
42#define MHD_E_SERVER_INIT "Error: failed to start server\n"
43#define MHD_E_TEST_FILE_CREAT "Error: failed to setup test file\n"
44#define MHD_E_CERT_FILE_CREAT "Error: failed to setup test certificate\n"
45#define MHD_E_KEY_FILE_CREAT "Error: failed to setup test certificate\n"
46
47#include "tls_test_keys.h"
48
49const char *test_file_name = "https_test_file";
50const char test_file_data[] = "Hello World\n";
51 41
52int curl_check_version (const char *req_version, ...); 42int curl_check_version (const char *req_version, ...);
53 43
54struct CBC
55{
56 char *buf;
57 size_t pos;
58 size_t size;
59};
60
61struct https_test_data
62{
63 FILE *test_fd;
64 char *cipher_suite;
65 int proto_version;
66};
67
68struct CipherDef
69{
70 int options[2];
71 char *curlname;
72};
73
74static size_t
75copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
76{
77 struct CBC *cbc = ctx;
78
79 if (cbc->pos + size * nmemb > cbc->size)
80 return 0; /* overflow */
81 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
82 cbc->pos += size * nmemb;
83 return size * nmemb;
84}
85
86static int
87file_reader (void *cls, size_t pos, char *buf, int max)
88{
89 FILE *file = cls;
90 fseek (file, pos, SEEK_SET);
91 return fread (buf, 1, max, file);
92}
93
94/* HTTP access handler call back */
95static int
96http_ahc (void *cls, struct MHD_Connection *connection,
97 const char *url, const char *method, const char *upload_data,
98 const char *version, unsigned int *upload_data_size, void **ptr)
99{
100 static int aptr;
101 struct MHD_Response *response;
102 int ret;
103 FILE *file;
104 struct stat buf;
105
106 if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
107 return MHD_NO; /* unexpected method */
108 if (&aptr != *ptr)
109 {
110 /* do never respond on first call */
111 *ptr = &aptr;
112 return MHD_YES;
113 }
114 *ptr = NULL; /* reset when done */
115
116 file = fopen (url, "r");
117 if (file == NULL)
118 {
119 response = MHD_create_response_from_data (strlen (PAGE_NOT_FOUND),
120 (void *) PAGE_NOT_FOUND,
121 MHD_NO, MHD_NO);
122 ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
123 MHD_destroy_response (response);
124 }
125 else
126 {
127 stat (url, &buf);
128 response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k PAGE_NOT_FOUND size */
129 &file_reader, file,
130 (MHD_ContentReaderFreeCallback)
131 & fclose);
132 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
133 MHD_destroy_response (response);
134 }
135 return ret;
136}
137
138
139
140/**
141 * test HTTPS transfer
142 * @param test_fd: file to attempt transfering
143 */
144static int
145test_https_transfer (FILE * test_fd, char *cipher_suite, int proto_version)
146{
147 CURL *c;
148 CURLcode errornum;
149 struct CBC cbc;
150 char *doc_path;
151 size_t doc_path_len;
152 char url[255];
153 struct stat statb;
154
155 stat (test_file_name, &statb);
156
157 int len = statb.st_size;
158
159 /* used to memcmp local copy & deamon supplied copy */
160 unsigned char *mem_test_file_local;
161
162 /* setup test file path, url */
163 doc_path_len = PATH_MAX > 4096 ? 4096 : PATH_MAX;
164 if (NULL == (doc_path = malloc (doc_path_len)))
165 {
166 fprintf (stderr, MHD_E_MEM);
167 return -1;
168 }
169 if (getcwd (doc_path, doc_path_len) == NULL)
170 {
171 fprintf (stderr, "Error: failed to get working directory. %s\n",
172 strerror (errno));
173 free (doc_path);
174 return -1;
175 }
176
177 if (NULL == (mem_test_file_local = malloc (len)))
178 {
179 fprintf (stderr, MHD_E_MEM);
180 free (doc_path);
181 return -1;
182 }
183
184 fseek (test_fd, 0, SEEK_SET);
185 if (fread (mem_test_file_local, sizeof (char), len, test_fd) != len)
186 {
187 fprintf (stderr, "Error: failed to read test file. %s\n",
188 strerror (errno));
189 free (doc_path);
190 free (mem_test_file_local);
191 return -1;
192 }
193
194 if (NULL == (cbc.buf = malloc (len)))
195 {
196 fprintf (stderr, MHD_E_MEM);
197 free (doc_path);
198 free (mem_test_file_local);
199 return -1;
200 }
201 cbc.size = len;
202 cbc.pos = 0;
203
204 /* construct url - this might use doc_path */
205 sprintf (url, "%s%s/%s", "https://localhost:42433",
206 doc_path, test_file_name);
207
208 c = curl_easy_init ();
209#if DEBUG_CURL_VERBOSE
210 curl_easy_setopt (c, CURLOPT_VERBOSE, 1);
211#endif
212 curl_easy_setopt (c, CURLOPT_URL, url);
213 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
214 curl_easy_setopt (c, CURLOPT_TIMEOUT, 15L);
215 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
216 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
217 curl_easy_setopt (c, CURLOPT_FILE, &cbc);
218
219 /* TLS options */
220 curl_easy_setopt (c, CURLOPT_SSLVERSION, proto_version);
221 curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, cipher_suite);
222
223 /* currently skip any peer authentication */
224 curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0);
225 curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0);
226
227 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
228
229 /* NOTE: use of CONNECTTIMEOUT without also
230 setting NOSIGNAL results in really weird
231 crashes on my system! */
232 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
233 if (CURLE_OK != (errornum = curl_easy_perform (c)))
234 {
235 fprintf (stderr, "curl_easy_perform failed: `%s'\n",
236 curl_easy_strerror (errornum));
237 curl_easy_cleanup (c);
238 free (cbc.buf);
239 free (mem_test_file_local);
240 free (doc_path);
241 return errornum;
242 }
243
244 curl_easy_cleanup (c);
245
246 if (memcmp (cbc.buf, mem_test_file_local, len) != 0)
247 {
248 fprintf (stderr, "Error: local file & received file differ.\n");
249 free (cbc.buf);
250 free (mem_test_file_local);
251 free (doc_path);
252 return -1;
253 }
254
255 free (mem_test_file_local);
256 free (cbc.buf);
257 free (doc_path);
258 return 0;
259}
260
261/** 44/**
262 * used when spawning multiple threads executing curl server requests 45 * used when spawning multiple threads executing curl server requests
263 * 46 *
@@ -278,92 +61,6 @@ https_transfer_thread_adapter (void *args)
278 return &nonnull; 61 return &nonnull;
279} 62}
280 63
281static FILE *
282setupTestFile ()
283{
284 FILE *test_fd;
285
286 if (NULL == (test_fd = fopen (test_file_name, "w+")))
287 {
288 fprintf (stderr, "Error: failed to open `%s': %s\n",
289 test_file_name, strerror (errno));
290 return NULL;
291 }
292 if (fwrite (test_file_data, sizeof (char), strlen (test_file_data), test_fd)
293 != strlen (test_file_data))
294 {
295 fprintf (stderr, "Error: failed to write `%s. %s'\n",
296 test_file_name, strerror (errno));
297 fclose (test_fd);
298 return NULL;
299 }
300 if (fflush (test_fd))
301 {
302 fprintf (stderr, "Error: failed to flush test file stream. %s\n",
303 strerror (errno));
304 fclose (test_fd);
305 return NULL;
306 }
307
308 return test_fd;
309}
310
311static int
312setup (struct MHD_Daemon **d, int daemon_flags, va_list arg_list)
313{
314 *d = MHD_start_daemon_va (daemon_flags, 42433,
315 NULL, NULL, &http_ahc, NULL, arg_list);
316
317 if (*d == NULL)
318 {
319 fprintf (stderr, MHD_E_SERVER_INIT);
320 return -1;
321 }
322
323 return 0;
324}
325
326static void
327teardown (struct MHD_Daemon *d)
328{
329 MHD_stop_daemon (d);
330}
331
332/* TODO test_wrap: change sig to (setup_func, test, va_list test_arg) & move to test_util.c */
333static int
334test_wrap (char *test_name, int
335 (*test_function) (FILE * test_fd, char *cipher_suite,
336 int proto_version), FILE * test_fd,
337 int daemon_flags, char *cipher_suite, int proto_version, ...)
338{
339 int ret;
340 va_list arg_list;
341 struct MHD_Daemon *d;
342
343 va_start (arg_list, proto_version);
344 if (setup (&d, daemon_flags, arg_list) != 0)
345 {
346 va_end (arg_list);
347 return -1;
348 }
349
350 fprintf (stdout, "running test: %s ", test_name);
351 ret = test_function (test_fd, cipher_suite, proto_version);
352
353 if (ret == 0)
354 {
355 fprintf (stdout, "[pass]\n");
356 }
357 else
358 {
359 fprintf (stdout, "[fail]\n");
360 }
361
362 teardown (d);
363 va_end (arg_list);
364 return ret;
365}
366
367/** 64/**
368 * Test non-parallel requests. 65 * Test non-parallel requests.
369 * 66 *
@@ -407,11 +104,10 @@ test_parallel_clients (FILE * test_fd, char *cipher_suite,
407 for (i = 0; i < client_count; ++i) 104 for (i = 0; i < client_count; ++i)
408 { 105 {
409 if (pthread_create (&client_arr[i], NULL, 106 if (pthread_create (&client_arr[i], NULL,
410 &https_transfer_thread_adapter, 107 &https_transfer_thread_adapter, &client_args) != 0)
411 &client_args) != 0)
412 { 108 {
413 fprintf (stderr, "Error: failed to spawn test client threads.\n"); 109 fprintf (stderr, "Error: failed to spawn test client threads.\n");
414 110
415 return -1; 111 return -1;
416 } 112 }
417 } 113 }
@@ -441,7 +137,7 @@ main (int argc, char *const *argv)
441 if (curl_check_version (MHD_REQ_CURL_VERSION)) 137 if (curl_check_version (MHD_REQ_CURL_VERSION))
442 return -1; 138 return -1;
443 139
444 if ((test_fd = setupTestFile ()) == NULL) 140 if ((test_fd = setup_test_file ()) == NULL)
445 { 141 {
446 fprintf (stderr, MHD_E_TEST_FILE_CREAT); 142 fprintf (stderr, MHD_E_TEST_FILE_CREAT);
447 return -1; 143 return -1;
@@ -456,14 +152,16 @@ main (int argc, char *const *argv)
456 152
457 errorCount += 153 errorCount +=
458 test_wrap ("multi threaded daemon, single client", &test_single_client, 154 test_wrap ("multi threaded daemon, single client", &test_single_client,
459 test_fd, MHD_USE_SSL | MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION, "AES256-SHA", 155 test_fd,
460 CURL_SSLVERSION_TLSv1, MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem, 156 MHD_USE_SSL | MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION,
461 MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem, 157 "AES256-SHA", CURL_SSLVERSION_TLSv1, MHD_OPTION_HTTPS_MEM_KEY,
462 MHD_OPTION_END); 158 srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT,
159 srv_self_signed_cert_pem, MHD_OPTION_END);
463 160
464 errorCount += 161 errorCount +=
465 test_wrap ("multi threaded daemon, parallel client", 162 test_wrap ("multi threaded daemon, parallel client",
466 &test_parallel_clients, test_fd, MHD_USE_SSL | MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION, 163 &test_parallel_clients, test_fd,
164 MHD_USE_SSL | MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION,
467 "AES256-SHA", CURL_SSLVERSION_TLSv1, MHD_OPTION_HTTPS_MEM_KEY, 165 "AES256-SHA", CURL_SSLVERSION_TLSv1, MHD_OPTION_HTTPS_MEM_KEY,
468 srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT, 166 srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT,
469 srv_self_signed_cert_pem, MHD_OPTION_END); 167 srv_self_signed_cert_pem, MHD_OPTION_END);
@@ -474,7 +172,7 @@ main (int argc, char *const *argv)
474 curl_global_cleanup (); 172 curl_global_cleanup ();
475 fclose (test_fd); 173 fclose (test_fd);
476 174
477 remove (test_file_name); 175 remove (TEST_FILE_NAME);
478 176
479 return errorCount != 0; 177 return errorCount != 0;
480} 178}