Skip to content

Commit 7c3e455

Browse files
committed
CDRIVER-630 test connect timeout and TLS handshake
1 parent ad701c2 commit 7c3e455

File tree

5 files changed

+148
-28
lines changed

5 files changed

+148
-28
lines changed

tests/ssl-test.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ typedef struct ssl_test_data
2828
mongoc_ssl_opt_t *client;
2929
mongoc_ssl_opt_t *server;
3030
ssl_test_behavior_t behavior;
31+
int64_t handshake_stall_ms;
3132
const char *host;
3233
unsigned short server_port;
3334
mongoc_cond_t cond;

tests/test-libmongoc.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,23 @@ extern void test_stream_tls_error_install (TestSuite *suite);
5252
#endif
5353

5454

55+
#ifdef _WIN32
56+
void
57+
usleep (int64_t usec)
58+
{
59+
HANDLE timer;
60+
LARGE_INTEGER ft;
61+
62+
ft.QuadPart = -(10 * usec);
63+
64+
timer = CreateWaitableTimer(NULL, true, NULL);
65+
SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
66+
WaitForSingleObject(timer, INFINITE);
67+
CloseHandle(timer);
68+
}
69+
#endif
70+
71+
5572
static int gSuppressCount;
5673
#ifdef MONGOC_ENABLE_SSL
5774
static mongoc_ssl_opt_t gSSLOptions;

tests/test-libmongoc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
#ifndef TEST_LIBMONGOC_H
1919
#define TEST_LIBMONGOC_H
2020

21+
22+
#ifdef _WIN32
23+
void usleep (int64_t usec);
24+
#endif
25+
26+
2127
char *gen_collection_name (const char *prefix);
2228
void suppress_one_message (void);
2329
char *test_framework_get_host (void);

tests/test-mongoc-client.c

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,6 @@
1515
#undef MONGOC_LOG_DOMAIN
1616
#define MONGOC_LOG_DOMAIN "client-test"
1717

18-
19-
#ifdef _WIN32
20-
static void
21-
usleep (int64_t usec)
22-
{
23-
HANDLE timer;
24-
LARGE_INTEGER ft;
25-
26-
ft.QuadPart = -(10 * usec);
27-
28-
timer = CreateWaitableTimer(NULL, true, NULL);
29-
SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
30-
WaitForSingleObject(timer, INFINITE);
31-
CloseHandle(timer);
32-
}
33-
#endif
34-
35-
3618
static mongoc_collection_t *
3719
get_test_collection (mongoc_client_t *client,
3820
const char *name)

tests/test-mongoc-stream-tls-error.c

Lines changed: 124 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,25 +69,29 @@ ssl_error_server (void *ptr)
6969
ssl_stream = mongoc_stream_tls_new (sock_stream, data->server, 0);
7070
assert (ssl_stream);
7171

72-
if (data->behavior != SSL_TEST_BEHAVIOR_STALL_BEFORE_HANDSHAKE) {
72+
switch (data->behavior) {
73+
case SSL_TEST_BEHAVIOR_STALL_BEFORE_HANDSHAKE:
74+
usleep (data->handshake_stall_ms * 1000);
75+
break;
76+
case SSL_TEST_BEHAVIOR_HANGUP_AFTER_HANDSHAKE:
7377
r = mongoc_stream_tls_do_handshake (ssl_stream, TIMEOUT);
7478
assert (r);
7579

7680
r = mongoc_stream_readv (ssl_stream, &iov, 1, 1, TIMEOUT);
7781
assert (r == 1);
78-
79-
/* this test function only implements two behaviors so far */
80-
ASSERT_CMPINT (data->behavior,
81-
==,
82-
SSL_TEST_BEHAVIOR_HANGUP_AFTER_HANDSHAKE);
83-
84-
mongoc_stream_close (ssl_stream);
85-
mongoc_stream_destroy (ssl_stream);
86-
mongoc_socket_destroy (listen_sock);
82+
break;
83+
case SSL_TEST_BEHAVIOR_NORMAL:
84+
default:
85+
fprintf (stderr, "unimplemented ssl_test_behavior_t\n");
86+
abort ();
8787
}
8888

8989
data->server_result->result = SSL_TEST_SUCCESS;
9090

91+
mongoc_stream_close (ssl_stream);
92+
mongoc_stream_destroy (ssl_stream);
93+
mongoc_socket_destroy (listen_sock);
94+
9195
return NULL;
9296
}
9397

@@ -206,8 +210,118 @@ test_mongoc_tls_hangup (void)
206210
ASSERT (sr.result == SSL_TEST_SUCCESS);
207211
}
208212

213+
214+
/** run as a child thread by test_mongoc_tls_handshake_stall
215+
*
216+
* It:
217+
* 1. spins up
218+
* 2. waits on a condvar until the server is up
219+
* 3. connects to the server's port
220+
* 4. attempts handshake
221+
* 5. confirms that it times out
222+
* 6. shuts down
223+
*/
224+
static void *
225+
handshake_stall_client (void *ptr)
226+
{
227+
ssl_test_data_t *data = (ssl_test_data_t *)ptr;
228+
char *uri_str;
229+
mongoc_client_t *client;
230+
bson_t reply;
231+
bson_error_t error;
232+
int64_t connect_timeout_ms = data->handshake_stall_ms - 100;
233+
int64_t duration_ms;
234+
235+
int64_t start_time;
236+
237+
mongoc_mutex_lock (&data->cond_mutex);
238+
while (!data->server_port) {
239+
mongoc_cond_wait (&data->cond, &data->cond_mutex);
240+
}
241+
mongoc_mutex_unlock (&data->cond_mutex);
242+
243+
uri_str = bson_strdup_printf (
244+
"mongodb://localhost:%u/?ssl=true&connecttimeoutms=%" PRId64,
245+
data->server_port, connect_timeout_ms);
246+
247+
client = mongoc_client_new (uri_str);
248+
249+
/* we should time out after about 200ms */
250+
start_time = bson_get_monotonic_time ();
251+
mongoc_client_get_server_status (client,
252+
NULL,
253+
&reply,
254+
&error);
255+
256+
/* time is in microseconds */
257+
duration_ms = (bson_get_monotonic_time () - start_time) / 1000;
258+
259+
if (llabs(duration_ms - connect_timeout_ms) > 100) {
260+
fprintf (stderr,
261+
"expected timeout after about 200ms, not %" PRId64 "\n",
262+
duration_ms);
263+
abort ();
264+
}
265+
266+
data->client_result->result = SSL_TEST_SUCCESS;
267+
268+
bson_destroy (&reply);
269+
mongoc_client_destroy (client);
270+
bson_free (uri_str);
271+
272+
return NULL;
273+
}
274+
275+
276+
static void
277+
test_mongoc_tls_handshake_stall (void)
278+
{
279+
mongoc_ssl_opt_t sopt = { 0 };
280+
mongoc_ssl_opt_t copt = { 0 };
281+
ssl_test_result_t sr;
282+
ssl_test_result_t cr;
283+
ssl_test_data_t data = { 0 };
284+
mongoc_thread_t threads[2];
285+
int i, r;
286+
287+
sopt.pem_file = PEMFILE_NOPASS;
288+
sopt.weak_cert_validation = 1;
289+
copt.weak_cert_validation = 1;
290+
291+
data.server = &sopt;
292+
data.client = &copt;
293+
data.behavior = SSL_TEST_BEHAVIOR_STALL_BEFORE_HANDSHAKE;
294+
data.handshake_stall_ms = 300;
295+
data.server_result = &sr;
296+
data.client_result = &cr;
297+
data.host = "localhost";
298+
299+
mongoc_mutex_init (&data.cond_mutex);
300+
mongoc_cond_init (&data.cond);
301+
302+
r = mongoc_thread_create (threads, &ssl_error_server, &data);
303+
assert (r == 0);
304+
305+
r =
306+
mongoc_thread_create (threads + 1, &handshake_stall_client, &data);
307+
assert (r == 0);
308+
309+
for (i = 0; i < 2; i++) {
310+
r = mongoc_thread_join (threads[i]);
311+
assert (r == 0);
312+
}
313+
314+
mongoc_mutex_destroy (&data.cond_mutex);
315+
mongoc_cond_destroy (&data.cond);
316+
317+
ASSERT (cr.result == SSL_TEST_SUCCESS);
318+
ASSERT (sr.result == SSL_TEST_SUCCESS);
319+
}
320+
209321
void
210322
test_stream_tls_error_install (TestSuite *suite)
211323
{
212324
TestSuite_Add (suite, "/TLS/hangup", test_mongoc_tls_hangup);
325+
TestSuite_Add (suite, "/TLS/handshake_stall",
326+
test_mongoc_tls_handshake_stall);
213327
}

0 commit comments

Comments
 (0)