/** This is the testing function for the ssl-test lib * * The basic idea is that you spin up a client and server, which will * communicate over a mongoc-stream-tls, with varying mongoc_ssl_opt's. The * client and server speak a simple echo protocol, so all we're really testing * here is that any given configuration succeeds or fails as it should */ void ssl_test (mongoc_ssl_opt_t *client, mongoc_ssl_opt_t *server, const char *host, ssl_test_result_t *client_result, ssl_test_result_t *server_result) { ssl_test_data_t data = {0}; mongoc_thread_t threads[2]; int i, r; data.server = server; data.client = client; data.client_result = client_result; data.server_result = server_result; data.host = host; mongoc_mutex_init (&data.cond_mutex); mongoc_cond_init (&data.cond); r = mongoc_thread_create (threads, &ssl_test_server, &data); BSON_ASSERT (r == 0); r = mongoc_thread_create (threads + 1, &ssl_test_client, &data); BSON_ASSERT (r == 0); for (i = 0; i < 2; i++) { r = mongoc_thread_join (threads[i]); BSON_ASSERT (r == 0); } mongoc_mutex_destroy (&data.cond_mutex); mongoc_cond_destroy (&data.cond); }
void mock_server_run_in_thread (mock_server_t *server) { BSON_ASSERT (server); server->using_main_thread = true; mongoc_thread_create (&server->main_thread, main_thread, server); }
static void test_mongoc_tls_handshake_stall (void) { mongoc_ssl_opt_t sopt = { 0 }; mongoc_ssl_opt_t copt = { 0 }; ssl_test_result_t sr; ssl_test_result_t cr; ssl_test_data_t data = { 0 }; mongoc_thread_t threads[2]; int i, r; sopt.pem_file = PEMFILE_NOPASS; sopt.weak_cert_validation = 1; copt.weak_cert_validation = 1; data.server = &sopt; data.client = &copt; data.behavior = SSL_TEST_BEHAVIOR_STALL_BEFORE_HANDSHAKE; data.handshake_stall_ms = 300; data.server_result = &sr; data.client_result = &cr; data.host = "localhost"; mongoc_mutex_init (&data.cond_mutex); mongoc_cond_init (&data.cond); r = mongoc_thread_create (threads, &ssl_error_server, &data); assert (r == 0); r = mongoc_thread_create (threads + 1, &handshake_stall_client, &data); assert (r == 0); for (i = 0; i < 2; i++) { r = mongoc_thread_join (threads[i]); assert (r == 0); } mongoc_mutex_destroy (&data.cond_mutex); mongoc_cond_destroy (&data.cond); ASSERT (cr.result == SSL_TEST_SUCCESS); ASSERT (sr.result == SSL_TEST_SUCCESS); }
void future_start (future_t *future, void *(*start_routine)(void *)) { int r = mongoc_thread_create (&future->thread, start_routine, (void *) future); assert (!r); }
void mock_server_run_in_thread (mock_server_t *server) { BSON_ASSERT (server); server->using_main_thread = true; mongoc_mutex_lock (&server->mutex); mongoc_thread_create (&server->main_thread, main_thread, server); mongoc_cond_wait (&server->cond, &server->mutex); mongoc_mutex_unlock (&server->mutex); }
static void test_mongoc_socket_sendv (void) { socket_test_data_t data = { 0 }; mongoc_thread_t threads[2]; int i, r; mongoc_mutex_init (&data.cond_mutex); mongoc_cond_init (&data.cond); r = mongoc_thread_create (threads, &sendv_test_server, &data); assert (r == 0); r = mongoc_thread_create (threads + 1, &sendv_test_client, &data); assert (r == 0); for (i = 0; i < 2; i++) { r = mongoc_thread_join (threads[i]); assert (r == 0); } mongoc_mutex_destroy (&data.cond_mutex); mongoc_cond_destroy (&data.cond); }
int mock_server_run (mock_server_t *server) { struct sockaddr_in saddr; mongoc_stream_t *stream; mongoc_thread_t thread; mongoc_socket_t *ssock; mongoc_socket_t *csock; void **closure; int optval; bson_return_val_if_fail (server, -1); bson_return_val_if_fail (!server->sock, -1); MONGOC_INFO ("Starting mock server on port %d.", server->port); ssock = mongoc_socket_new (AF_INET, SOCK_STREAM, 0); if (!ssock) { perror("Failed to create socket."); return -1; } optval = 1; mongoc_socket_setsockopt (ssock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval); memset (&saddr, 0, sizeof saddr); saddr.sin_family = AF_INET; saddr.sin_port = htons(server->port); /* * TODO: Parse server->address. */ saddr.sin_addr.s_addr = htonl (INADDR_ANY); if (-1 == mongoc_socket_bind (ssock, (struct sockaddr *)&saddr, sizeof saddr)) { perror("Failed to bind socket"); return -1; } if (-1 == mongoc_socket_listen (ssock, 10)) { perror("Failed to put socket into listen mode"); return 3; } server->sock = ssock; mongoc_mutex_lock (&server->mutex); mongoc_cond_signal (&server->cond); mongoc_mutex_unlock (&server->mutex); for (;;) { csock = mongoc_socket_accept (server->sock, -1); if (!csock) { perror ("Failed to accept client socket"); break; } stream = mongoc_stream_socket_new (csock); closure = bson_malloc0 (sizeof(void*) * 2); closure[0] = server; closure[1] = stream; mongoc_thread_create (&thread, mock_server_worker, closure); } mongoc_socket_close (server->sock); server->sock = NULL; return 0; }
uint16_t mock_server_run (mock_server_t *server) { mongoc_socket_t *ssock; struct sockaddr_in bind_addr; int optval; uint16_t bound_port; MONGOC_INFO ("Starting mock server on port %d.", server->port); ssock = mongoc_socket_new (AF_INET, SOCK_STREAM, 0); if (!ssock) { perror ("Failed to create socket."); return 0; } optval = 1; mongoc_socket_setsockopt (ssock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval); memset (&bind_addr, 0, sizeof bind_addr); bind_addr.sin_family = AF_INET; bind_addr.sin_addr.s_addr = htonl (INADDR_ANY); /* bind to unused port */ bind_addr.sin_port = htons (0); if (-1 == mongoc_socket_bind (ssock, (struct sockaddr *) &bind_addr, sizeof bind_addr)) { perror ("Failed to bind socket"); return 0; } if (-1 == mongoc_socket_listen (ssock, 10)) { perror ("Failed to put socket into listen mode"); return 0; } bound_port = get_port (ssock); if (!bound_port) { perror ("Failed to get bound port number"); return 0; } mongoc_mutex_lock (&server->mutex); server->sock = ssock; server->port = bound_port; /* TODO: configurable timeouts, perhaps from env */ server->uri_str = bson_strdup_printf ( "mongodb://127.0.0.1:%hu/?serverselectiontimeoutms=10000&" "sockettimeoutms=10000", bound_port); server->uri = mongoc_uri_new (server->uri_str); mongoc_thread_create (&server->main_thread, main_thread, (void *) server); /* wait for main thread to start */ mongoc_cond_wait (&server->cond, &server->mutex); mongoc_mutex_unlock (&server->mutex); if (mock_server_get_verbose (server)) { fprintf (stderr, "listening on port %hu\n", bound_port); fflush (stdout); } return (uint16_t) bound_port; }
static void * main_thread (void *data) { mock_server_t *server = (mock_server_t *)data; mongoc_socket_t *client_sock; bool stopped; uint16_t port; mongoc_stream_t *client_stream; worker_closure_t *closure; mongoc_thread_t thread; mongoc_array_t worker_threads; size_t i; mongoc_mutex_lock (&server->mutex); server->running = true; mongoc_cond_signal (&server->cond); mongoc_mutex_unlock (&server->mutex); for (; ;) { client_sock = mongoc_socket_accept_ex ( server->sock, bson_get_monotonic_time () + TIMEOUT, &port); mongoc_mutex_lock (&server->mutex); stopped = server->stopped; mongoc_mutex_unlock (&server->mutex); if (stopped) { break; } if (client_sock) { if (mock_server_get_verbose (server)) { printf ("%5.2f %hu -> server port %hu (connected)\n", mock_server_get_uptime_sec (server), port, server->port); fflush (stdout); } client_stream = mongoc_stream_socket_new (client_sock); #ifdef MONGOC_ENABLE_SSL mongoc_mutex_lock (&server->mutex); if (server->ssl) { server->ssl_opts.weak_cert_validation = 1; client_stream = mongoc_stream_tls_new (client_stream, &server->ssl_opts, 0); if (!client_stream) { mongoc_mutex_unlock (&server->mutex); perror ("Failed to attach tls stream"); break; } } mongoc_mutex_unlock (&server->mutex); #endif closure = (worker_closure_t *)bson_malloc (sizeof *closure); closure->server = server; closure->client_stream = client_stream; closure->port = port; mongoc_thread_create (&thread, worker_thread, closure); mongoc_mutex_lock (&server->mutex); _mongoc_array_append_val (&server->worker_threads, thread); mongoc_mutex_unlock (&server->mutex); } } /* copy list of worker threads and join them all */ _mongoc_array_init (&worker_threads, sizeof (mongoc_thread_t)); mongoc_mutex_lock (&server->mutex); _mongoc_array_copy (&worker_threads, &server->worker_threads); mongoc_mutex_unlock (&server->mutex); for (i = 0; i < worker_threads.len; i++) { mongoc_thread_join ( _mongoc_array_index (&worker_threads, mongoc_thread_t, i)); } _mongoc_array_destroy (&worker_threads); mongoc_mutex_lock (&server->mutex); server->running = false; mongoc_mutex_unlock (&server->mutex); return NULL; }
int mock_server_run (mock_server_t *server) { struct sockaddr_in saddr; mongoc_stream_t *stream; mongoc_thread_t thread; void **closure; int optval; mongoc_fd_t sd; mongoc_fd_t cd; bson_return_val_if_fail(server, -1); bson_return_val_if_fail(! mongoc_fd_is_valid(server->socket), -1); sd = mongoc_socket(AF_INET, SOCK_STREAM, 0); if (! mongoc_fd_is_valid(sd)) { perror("Failed to create socket."); return -1; } optval = 1; mongoc_setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval); memset(&saddr, 0, sizeof saddr); saddr.sin_family = AF_INET; saddr.sin_port = htons(server->port); /* * TODO: Parse server->address. */ saddr.sin_addr.s_addr = htonl(INADDR_ANY); if (-1 == mongoc_bind(sd, (struct sockaddr *)&saddr, sizeof saddr)) { perror("Failed to bind socket"); return -1; } if (-1 == mongoc_listen(sd, 10)) { perror("Failed to put socket into listen mode"); return 3; } server->socket = sd; for (;;) { cd = mongoc_accept(server->socket, NULL, NULL); if (! mongoc_fd_is_valid(cd)) { perror("Failed to accept client socket"); return -1; } stream = mongoc_stream_unix_new(cd); closure = bson_malloc0(sizeof(void*) * 2); closure[0] = server; closure[1] = stream; mongoc_thread_create(&thread, mock_server_worker, closure); } mongoc_close(server->socket); server->socket = MONGOC_FD_INVALID; return 0; }