static void test_buffered_basic (void) { mongoc_stream_t *stream; mongoc_stream_t *buffered; ssize_t r; struct iovec iov; char buf[16236]; mongoc_fd_t fd; fd = mongoc_open("tests/binary/reply2.dat", O_RDONLY); assert(mongoc_fd_is_valid(fd)); /* stream assumes ownership of fd */ stream = mongoc_stream_unix_new(fd); /* buffered assumes ownership of stream */ buffered = mongoc_stream_buffered_new(stream, 1024); /* try to read large chunk larger than buffer. */ iov.iov_len = sizeof buf; iov.iov_base = buf; r = mongoc_stream_readv(buffered, &iov, 1, iov.iov_len, -1); BSON_ASSERT(r == iov.iov_len); /* cleanup */ mongoc_stream_destroy(buffered); }
/** run as a child thread by test_mongoc_tls_hangup * * It: * 1. spins up * 2. waits on a condvar until the server is up * 3. connects to the server's port * 4. writes a byte * 5. confirms that the server hangs up promptly * 6. shuts down */ static void * ssl_hangup_client (void *ptr) { ssl_test_data_t *data = (ssl_test_data_t *)ptr; mongoc_stream_t *sock_stream; mongoc_stream_t *ssl_stream; mongoc_socket_t *conn_sock; char buf = 'b'; ssize_t r; mongoc_iovec_t riov; mongoc_iovec_t wiov; struct sockaddr_in server_addr = { 0 }; int64_t start_time; bson_error_t error; conn_sock = mongoc_socket_new (AF_INET, SOCK_STREAM, 0); assert (conn_sock); mongoc_mutex_lock (&data->cond_mutex); while (!data->server_port) { mongoc_cond_wait (&data->cond, &data->cond_mutex); } mongoc_mutex_unlock (&data->cond_mutex); server_addr.sin_family = AF_INET; server_addr.sin_port = htons (data->server_port); server_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); r = mongoc_socket_connect (conn_sock, (struct sockaddr *)&server_addr, sizeof (server_addr), -1); assert (r == 0); sock_stream = mongoc_stream_socket_new (conn_sock); assert (sock_stream); ssl_stream = mongoc_stream_tls_new (sock_stream, data->client, 1); assert (ssl_stream); r = mongoc_stream_tls_handshake_block (ssl_stream, data->host, TIMEOUT, &error); assert (r); wiov.iov_base = (void *)&buf; wiov.iov_len = 1; r = mongoc_stream_writev (ssl_stream, &wiov, 1, TIMEOUT); assert (r == 1); riov.iov_base = (void *)&buf; riov.iov_len = 1; /* we should notice promptly that the server hangs up */ start_time = bson_get_monotonic_time (); r = mongoc_stream_readv (ssl_stream, &riov, 1, 1, TIMEOUT); /* time is in microseconds */ assert (bson_get_monotonic_time () - start_time < 1000 * 1000); assert (r == -1); mongoc_stream_destroy (ssl_stream); data->client_result->result = SSL_TEST_SUCCESS; return NULL; }
static ssize_t _mongoc_stream_debug_readv (mongoc_stream_t *stream, mongoc_iovec_t *iov, size_t iovcnt, size_t min_bytes, int32_t timeout_msec) { return mongoc_stream_readv (((mongoc_stream_debug_t *) stream)->wrapped, iov, iovcnt, min_bytes, timeout_msec); }
static ssize_t mongoc_stream_buffered_readv (mongoc_stream_t *stream, struct iovec *iov, size_t iovcnt, bson_uint32_t timeout_msec) { mongoc_stream_buffered_t *buffered = (mongoc_stream_buffered_t *)stream; bson_return_val_if_fail(buffered, -1); /* * TODO: Implement buffering. */ return mongoc_stream_readv(buffered->base_stream, iov, iovcnt, timeout_msec); }
static void test_stream (void) { mongoc_gridfs_t *gridfs; mongoc_gridfs_file_t *file; mongoc_client_t *client; mongoc_stream_t *stream; mongoc_stream_t *in_stream; bson_error_t error; ssize_t r; char buf[4096]; mongoc_iovec_t iov; iov.iov_base = buf; iov.iov_len = sizeof buf; client = mongoc_client_new (gTestUri); assert (client); gridfs = get_test_gridfs (client, "fs", &error); assert (gridfs); mongoc_gridfs_drop (gridfs, &error); in_stream = mongoc_stream_file_new_for_path (BINARY_DIR"/gridfs.dat", O_RDONLY, 0); file = mongoc_gridfs_create_file_from_stream (gridfs, in_stream, NULL); assert (file); assert (mongoc_gridfs_file_save (file)); stream = mongoc_stream_gridfs_new (file); r = mongoc_stream_readv (stream, &iov, 1, file->length, 0); assert (r == file->length); /* cleanup */ mongoc_stream_destroy (stream); mongoc_gridfs_file_destroy (file); drop_collections (gridfs, &error); mongoc_gridfs_destroy (gridfs); mongoc_client_destroy (client); }
/** * mongoc_stream_read: * @stream: A mongoc_stream_t. * @buf: A buffer to write into. * @count: The number of bytes to write into @buf. * @min_bytes: The minimum number of bytes to receive * * Simplified access to mongoc_stream_readv(). Creates a single iovec * with the buffer provided. * * If @min_bytes is specified, then at least min_bytes will be returned unless * eof is encountered. This may result in ETIMEDOUT * * Returns: -1 on failure, otherwise the number of bytes read. */ ssize_t mongoc_stream_read (mongoc_stream_t *stream, void *buf, size_t count, size_t min_bytes, int32_t timeout_msec) { struct iovec iov; bson_return_val_if_fail(stream, -1); bson_return_val_if_fail(buf, -1); iov.iov_base = buf; iov.iov_len = count; BSON_ASSERT(stream->readv); return mongoc_stream_readv(stream, &iov, 1, min_bytes, timeout_msec); }
/** * mongoc_stream_read: * @stream: A mongoc_stream_t. * @buf: A buffer to write into. * @count: The number of bytes to write into @buf. * @min_bytes: The minimum number of bytes to receive * * Simplified access to mongoc_stream_readv(). Creates a single iovec * with the buffer provided. * * If @min_bytes is specified, then at least min_bytes will be returned unless * eof is encountered. This may result in ETIMEDOUT * * Returns: -1 on failure, otherwise the number of bytes read. */ ssize_t mongoc_stream_read (mongoc_stream_t *stream, void *buf, size_t count, size_t min_bytes, int32_t timeout_msec) { mongoc_iovec_t iov; ssize_t ret; ENTRY; BSON_ASSERT (stream); BSON_ASSERT (buf); iov.iov_base = buf; iov.iov_len = count; BSON_ASSERT (stream->readv); ret = mongoc_stream_readv (stream, &iov, 1, min_bytes, timeout_msec); RETURN (ret); }
/** this function is meant to be run from ssl_test as a child thread * * It: * 1. spins up * 2. binds and listens to a random port * 3. notifies the client of it's port through a condvar * 4. accepts a request * 5. reads a 32 bit length * 6. reads a string of that length * 7. echos it back to the client * 8. shuts down */ static void * ssl_test_server (void * ptr) { ssl_test_data_t *data = (ssl_test_data_t *)ptr; mongoc_stream_t *sock_stream; mongoc_stream_t *ssl_stream; mongoc_socket_t *listen_sock; mongoc_socket_t *conn_sock; socklen_t sock_len; char buf[1024]; ssize_t r; mongoc_iovec_t iov; struct sockaddr_in server_addr = { 0 }; int len; iov.iov_base = buf; iov.iov_len = sizeof buf; listen_sock = mongoc_socket_new (AF_INET, SOCK_STREAM, 0); assert (listen_sock); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl (INADDR_ANY); server_addr.sin_port = htons (0); r = mongoc_socket_bind (listen_sock, (struct sockaddr *)&server_addr, sizeof server_addr); assert (r == 0); sock_len = sizeof(server_addr); r = mongoc_socket_getsockname (listen_sock, (struct sockaddr *)&server_addr, &sock_len); assert(r == 0); r = mongoc_socket_listen (listen_sock, 10); assert(r == 0); mongoc_mutex_lock(&data->cond_mutex); data->server_port = ntohs(server_addr.sin_port); mongoc_cond_signal(&data->cond); mongoc_mutex_unlock(&data->cond_mutex); conn_sock = mongoc_socket_accept (listen_sock, -1); assert (conn_sock); sock_stream = mongoc_stream_socket_new (conn_sock); assert (sock_stream); ssl_stream = mongoc_stream_tls_new(sock_stream, data->server, 0); if (!ssl_stream) { unsigned long err = ERR_get_error(); assert(err); data->server_result->ssl_err = err; data->server_result->result = SSL_TEST_SSL_INIT; mongoc_stream_destroy (sock_stream); mongoc_socket_destroy (listen_sock); return NULL; } assert(ssl_stream); r = mongoc_stream_tls_do_handshake (ssl_stream, TIMEOUT); if (!r) { unsigned long err = ERR_get_error(); assert(err); data->server_result->ssl_err = err; data->server_result->result = SSL_TEST_SSL_HANDSHAKE; mongoc_socket_destroy (listen_sock); mongoc_stream_destroy(ssl_stream); return NULL; } r = mongoc_stream_readv(ssl_stream, &iov, 1, 4, TIMEOUT); if (r < 0) { #ifdef _WIN32 assert(errno == WSAETIMEDOUT); #else assert(errno == ETIMEDOUT); #endif data->server_result->err = errno; data->server_result->result = SSL_TEST_TIMEOUT; mongoc_stream_destroy(ssl_stream); mongoc_socket_destroy (listen_sock); return NULL; } assert(r == 4); memcpy(&len, iov.iov_base, r); r = mongoc_stream_readv(ssl_stream, &iov, 1, len, TIMEOUT); assert(r == len); iov.iov_len = r; mongoc_stream_writev(ssl_stream, &iov, 1, TIMEOUT); mongoc_stream_destroy(ssl_stream); mongoc_socket_destroy (listen_sock); data->server_result->result = SSL_TEST_SUCCESS; return NULL; }
/** this function is meant to be run from ssl_test as a child thread * * It: * 1. spins up * 2. waits on a condvar until the server is up * 3. connects to the servers port * 4. writes a 4 bytes length * 5. writes a string of length size * 6. reads a response back of the given length * 7. confirms that its the same as what was written * 8. shuts down */ static void * ssl_test_client (void * ptr) { ssl_test_data_t *data = (ssl_test_data_t *)ptr; mongoc_stream_t *sock_stream; mongoc_stream_t *ssl_stream; mongoc_socket_t *conn_sock; char buf[1024]; ssize_t r; mongoc_iovec_t riov; mongoc_iovec_t wiov; struct sockaddr_in server_addr = { 0 }; int len; riov.iov_base = buf; riov.iov_len = sizeof buf; conn_sock = mongoc_socket_new (AF_INET, SOCK_STREAM, 0); assert (conn_sock); mongoc_mutex_lock(&data->cond_mutex); while (! data->server_port) { mongoc_cond_wait(&data->cond, &data->cond_mutex); } mongoc_mutex_unlock(&data->cond_mutex); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(data->server_port); r = inet_pton(AF_INET, LOCALHOST, &server_addr.sin_addr); assert (r > 0); r = mongoc_socket_connect (conn_sock, (struct sockaddr *)&server_addr, sizeof(server_addr), -1); assert (r == 0); sock_stream = mongoc_stream_socket_new (conn_sock); assert(sock_stream); ssl_stream = mongoc_stream_tls_new(sock_stream, data->client, 1); if (! ssl_stream) { unsigned long err = ERR_get_error(); assert(err); data->client_result->ssl_err = err; data->client_result->result = SSL_TEST_SSL_INIT; mongoc_stream_destroy(sock_stream); return NULL; } assert(ssl_stream); errno = 0; r = mongoc_stream_tls_do_handshake (ssl_stream, TIMEOUT); if (! r) { unsigned long err = ERR_get_error(); assert(err || errno); if (err) { data->client_result->ssl_err = err; } else { data->client_result->err = errno; } data->client_result->result = SSL_TEST_SSL_HANDSHAKE; mongoc_stream_destroy(ssl_stream); return NULL; } r = mongoc_stream_tls_check_cert (ssl_stream, data->host); if (! r) { data->client_result->result = SSL_TEST_SSL_VERIFY; mongoc_stream_destroy(ssl_stream); return NULL; } len = 4; wiov.iov_base = (void *)&len; wiov.iov_len = 4; r = mongoc_stream_writev(ssl_stream, &wiov, 1, TIMEOUT); assert(r == wiov.iov_len); wiov.iov_base = "foo"; wiov.iov_len = 4; r = mongoc_stream_writev(ssl_stream, &wiov, 1, TIMEOUT); assert(r == wiov.iov_len); r = mongoc_stream_readv(ssl_stream, &riov, 1, 4, TIMEOUT); assert(r > 0); assert(r == wiov.iov_len); assert(strcmp(riov.iov_base, wiov.iov_base) == 0); mongoc_stream_destroy(ssl_stream); data->client_result->result = SSL_TEST_SUCCESS; return NULL; }
/** run as a child thread by test_mongoc_tls_hangup * * It: * 1. spins up * 2. binds and listens to a random port * 3. notifies the client of its port through a condvar * 4. accepts a request * 5. reads a byte * 7. hangs up */ static void * ssl_error_server (void *ptr) { ssl_test_data_t *data = (ssl_test_data_t *)ptr; mongoc_stream_t *sock_stream; mongoc_stream_t *ssl_stream; mongoc_socket_t *listen_sock; mongoc_socket_t *conn_sock; socklen_t sock_len; char buf; ssize_t r; mongoc_iovec_t iov; struct sockaddr_in server_addr = { 0 }; iov.iov_base = &buf; iov.iov_len = 1; listen_sock = mongoc_socket_new (AF_INET, SOCK_STREAM, 0); assert (listen_sock); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); server_addr.sin_port = htons (0); r = mongoc_socket_bind (listen_sock, (struct sockaddr *)&server_addr, sizeof server_addr); assert (r == 0); sock_len = sizeof (server_addr); r = mongoc_socket_getsockname (listen_sock, (struct sockaddr *)&server_addr, &sock_len); assert (r == 0); r = mongoc_socket_listen (listen_sock, 10); assert (r == 0); mongoc_mutex_lock (&data->cond_mutex); data->server_port = ntohs (server_addr.sin_port); mongoc_cond_signal (&data->cond); mongoc_mutex_unlock (&data->cond_mutex); conn_sock = mongoc_socket_accept (listen_sock, -1); assert (conn_sock); sock_stream = mongoc_stream_socket_new (conn_sock); assert (sock_stream); ssl_stream = mongoc_stream_tls_new (sock_stream, data->server, 0); assert (ssl_stream); switch (data->behavior) { case SSL_TEST_BEHAVIOR_STALL_BEFORE_HANDSHAKE: _mongoc_usleep (data->handshake_stall_ms * 1000); break; case SSL_TEST_BEHAVIOR_HANGUP_AFTER_HANDSHAKE: r = mongoc_stream_tls_do_handshake (ssl_stream, TIMEOUT); assert (r); r = mongoc_stream_readv (ssl_stream, &iov, 1, 1, TIMEOUT); assert (r == 1); break; case SSL_TEST_BEHAVIOR_NORMAL: default: fprintf (stderr, "unimplemented ssl_test_behavior_t\n"); abort (); } data->server_result->result = SSL_TEST_SUCCESS; mongoc_stream_close (ssl_stream); mongoc_stream_destroy (ssl_stream); mongoc_socket_destroy (listen_sock); return NULL; }
int main (int argc, char *argv[]) { mongoc_gridfs_t *gridfs; mongoc_gridfs_file_t *file; mongoc_gridfs_file_list_t *list; mongoc_gridfs_file_opt_t opt = { 0 }; mongoc_client_t *client; mongoc_stream_t *stream; bson_t query; bson_t child; bson_error_t error; ssize_t r; char buf[4096]; mongoc_iovec_t iov; const char * filename; const char * command; if (argc < 2) { fprintf(stderr, "usage - %s command ...\n", argv[0]); return 1; } mongoc_init(); iov.iov_base = (void *)buf; iov.iov_len = sizeof buf; /* connect to localhost client */ client = mongoc_client_new ("mongodb://127.0.0.1:27017"); assert(client); /* grab a gridfs handle in test prefixed by fs */ gridfs = mongoc_client_get_gridfs (client, "test", "fs", &error); assert(gridfs); command = argv[1]; filename = argv[2]; if (strcmp(command, "read") == 0) { if (argc != 3) { fprintf(stderr, "usage - %s read filename\n", argv[0]); return 1; } file = mongoc_gridfs_find_one_by_filename(gridfs, filename, &error); assert(file); stream = mongoc_stream_gridfs_new (file); assert(stream); for (;;) { r = mongoc_stream_readv (stream, &iov, 1, -1, 0); assert (r >= 0); if (r == 0) { break; } if (fwrite (iov.iov_base, 1, r, stdout) != r) { MONGOC_ERROR ("Failed to write to stdout. Exiting.\n"); exit (1); } } mongoc_stream_destroy (stream); mongoc_gridfs_file_destroy (file); } else if (strcmp(command, "list") == 0) { bson_init (&query); bson_append_document_begin (&query, "$orderby", -1, &child); bson_append_int32 (&child, "filename", -1, 1); bson_append_document_end (&query, &child); bson_append_document_begin (&query, "$query", -1, &child); bson_append_document_end (&query, &child); list = mongoc_gridfs_find (gridfs, &query); bson_destroy (&query); while ((file = mongoc_gridfs_file_list_next (list))) { const char * name = mongoc_gridfs_file_get_filename(file); printf("%s\n", name ? name : "?"); mongoc_gridfs_file_destroy (file); } mongoc_gridfs_file_list_destroy (list); } else if (strcmp(command, "write") == 0) { if (argc != 4) { fprintf(stderr, "usage - %s write filename input_file\n", argv[0]); return 1; } stream = mongoc_stream_file_new_for_path (argv [3], O_RDONLY, 0); assert (stream); opt.filename = filename; file = mongoc_gridfs_create_file_from_stream (gridfs, stream, &opt); assert(file); mongoc_gridfs_file_save(file); mongoc_gridfs_file_destroy(file); } else { fprintf(stderr, "Unknown command"); return 1; } mongoc_gridfs_destroy (gridfs); mongoc_client_destroy (client); mongoc_cleanup (); return 0; }
int main (int argc, char *argv[]) { mongoc_gridfs_t *gridfs; mongoc_gridfs_file_t *file; mongoc_gridfs_file_list_t *list; mongoc_gridfs_file_opt_t opt = {0}; mongoc_client_t *client; mongoc_stream_t *stream; bson_t filter; bson_t opts; bson_t child; bson_error_t error; ssize_t r; char buf[4096]; mongoc_iovec_t iov; const char *filename; const char *command; bson_value_t id; if (argc < 2) { fprintf (stderr, "usage - %s command ...\n", argv[0]); return 1; } mongoc_init (); iov.iov_base = (void *) buf; iov.iov_len = sizeof buf; /* connect to localhost client */ client = mongoc_client_new ("mongodb://127.0.0.1:27017?appname=gridfs-example"); assert (client); mongoc_client_set_error_api (client, 2); /* grab a gridfs handle in test prefixed by fs */ gridfs = mongoc_client_get_gridfs (client, "test", "fs", &error); assert (gridfs); command = argv[1]; filename = argv[2]; if (strcmp (command, "read") == 0) { if (argc != 3) { fprintf (stderr, "usage - %s read filename\n", argv[0]); return 1; } file = mongoc_gridfs_find_one_by_filename (gridfs, filename, &error); assert (file); stream = mongoc_stream_gridfs_new (file); assert (stream); for (;;) { r = mongoc_stream_readv (stream, &iov, 1, -1, 0); assert (r >= 0); if (r == 0) { break; } if (fwrite (iov.iov_base, 1, r, stdout) != r) { MONGOC_ERROR ("Failed to write to stdout. Exiting.\n"); exit (1); } } mongoc_stream_destroy (stream); mongoc_gridfs_file_destroy (file); } else if (strcmp (command, "list") == 0) { bson_init (&filter); bson_init (&opts); bson_append_document_begin (&opts, "sort", -1, &child); BSON_APPEND_INT32 (&child, "filename", 1); bson_append_document_end (&opts, &child); list = mongoc_gridfs_find_with_opts (gridfs, &filter, &opts); bson_destroy (&filter); bson_destroy (&opts); while ((file = mongoc_gridfs_file_list_next (list))) { const char *name = mongoc_gridfs_file_get_filename (file); printf ("%s\n", name ? name : "?"); mongoc_gridfs_file_destroy (file); } mongoc_gridfs_file_list_destroy (list); } else if (strcmp (command, "write") == 0) { if (argc != 4) { fprintf (stderr, "usage - %s write filename input_file\n", argv[0]); return 1; } stream = mongoc_stream_file_new_for_path (argv[3], O_RDONLY, 0); assert (stream); opt.filename = filename; /* the driver generates a file_id for you */ file = mongoc_gridfs_create_file_from_stream (gridfs, stream, &opt); assert (file); id.value_type = BSON_TYPE_INT32; id.value.v_int32 = 1; /* optional: the following method specifies a file_id of any BSON type */ if (!mongoc_gridfs_file_set_id (file, &id, &error)) { fprintf (stderr, "%s\n", error.message); return 1; } mongoc_gridfs_file_save (file); mongoc_gridfs_file_destroy (file); } else { fprintf (stderr, "Unknown command"); return 1; } mongoc_gridfs_destroy (gridfs); mongoc_client_destroy (client); mongoc_cleanup (); return 0; }
static void * socket_test_server (void *data_) { socket_test_data_t *data = (socket_test_data_t *)data_; struct sockaddr_in server_addr = { 0 }; mongoc_socket_t *listen_sock; mongoc_socket_t *conn_sock; mongoc_stream_t *stream; mongoc_iovec_t iov; socklen_t sock_len; ssize_t r; char buf[5]; iov.iov_base = buf; iov.iov_len = sizeof (buf); listen_sock = mongoc_socket_new (AF_INET, SOCK_STREAM, 0); assert (listen_sock); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); server_addr.sin_port = htons (0); r = mongoc_socket_bind (listen_sock, (struct sockaddr *)&server_addr, sizeof server_addr); assert (r == 0); sock_len = sizeof(server_addr); r = mongoc_socket_getsockname (listen_sock, (struct sockaddr *)&server_addr, &sock_len); assert(r == 0); r = mongoc_socket_listen (listen_sock, 10); assert(r == 0); mongoc_mutex_lock(&data->cond_mutex); data->server_port = ntohs(server_addr.sin_port); mongoc_cond_signal(&data->cond); mongoc_mutex_unlock(&data->cond_mutex); conn_sock = mongoc_socket_accept (listen_sock, -1); assert (conn_sock); stream = mongoc_stream_socket_new (conn_sock); assert (stream); r = mongoc_stream_readv (stream, &iov, 1, 5, TIMEOUT); assert (r == 5); assert (strcmp (buf, "ping") == 0); strcpy (buf, "pong"); r = mongoc_stream_writev (stream, &iov, 1, TIMEOUT); assert (r == 5); mongoc_stream_destroy (stream); mongoc_mutex_lock(&data->cond_mutex); data->closed_socket = true; mongoc_cond_signal(&data->cond); mongoc_mutex_unlock(&data->cond_mutex); mongoc_socket_destroy (listen_sock); return NULL; }
static void * sendv_test_server (void *data_) { socket_test_data_t *data = (socket_test_data_t *)data_; struct sockaddr_in server_addr = { 0 }; mongoc_socket_t *listen_sock; mongoc_socket_t *conn_sock; mongoc_stream_t *stream; mongoc_iovec_t iov; socklen_t sock_len; int amount = 0; ssize_t r; char *buf = (char *)bson_malloc (gFourMB); iov.iov_base = buf; iov.iov_len = gFourMB; listen_sock = mongoc_socket_new (AF_INET, SOCK_STREAM, 0); assert (listen_sock); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); server_addr.sin_port = htons (0); r = mongoc_socket_bind (listen_sock, (struct sockaddr *)&server_addr, sizeof server_addr); assert (r == 0); sock_len = sizeof(server_addr); r = mongoc_socket_getsockname (listen_sock, (struct sockaddr *)&server_addr, &sock_len); assert(r == 0); r = mongoc_socket_listen (listen_sock, 10); assert(r == 0); mongoc_mutex_lock(&data->cond_mutex); data->server_port = ntohs(server_addr.sin_port); mongoc_cond_signal(&data->cond); mongoc_mutex_unlock(&data->cond_mutex); conn_sock = mongoc_socket_accept (listen_sock, -1); assert (conn_sock); stream = mongoc_stream_socket_new (conn_sock); assert (stream); /* Wait until the client has pushed so much data he can't write more */ mongoc_mutex_lock(&data->cond_mutex); while (! data->amount) { mongoc_cond_wait(&data->cond, &data->cond_mutex); } amount = data->amount; data->amount = 0; mongoc_mutex_unlock(&data->cond_mutex); /* Start reading everything off the socket to unblock the client */ do { r = mongoc_stream_readv (stream, &iov, 1, amount, WAIT); if (r > 0) { amount -= r; } else if (MONGOC_ERRNO_IS_AGAIN(errno)) { continue; } else { fprintf(stderr, "r: %"PRIu64" , errno: %d", (uint64_t)r, conn_sock->errno_); assert (r == amount); } } while (amount > 0); /* Allow the client to finish all its writes */ mongoc_mutex_lock(&data->cond_mutex); while (! data->amount) { mongoc_cond_wait(&data->cond, &data->cond_mutex); } /* amount is likely negative value now, we've read more then caused the original blocker */ amount += data->amount; data->amount = 0; mongoc_mutex_unlock(&data->cond_mutex); do { r = mongoc_stream_readv (stream, &iov, 1, amount, WAIT); if (r > 0) { amount -= r; } else if (MONGOC_ERRNO_IS_AGAIN(errno)) { continue; } else { fprintf(stderr, "r: %"PRIu64" , errno: %d", (uint64_t)r, errno); assert (r == amount); } } while (amount > 0); ASSERT_CMPINT(0, ==, amount); mongoc_stream_destroy (stream); mongoc_socket_destroy (listen_sock); return NULL; }
/** this function is meant to be run from ssl_test as a child thread * * It: * 1. spins up * 2. waits on a condvar until the server is up * 3. connects to the servers port * 4. writes a 4 bytes length * 5. writes a string of length size * 6. reads a response back of the given length * 7. confirms that its the same as what was written * 8. shuts down */ static void * ssl_test_client (void * ptr) { ssl_test_data_t *data = (ssl_test_data_t *)ptr; mongoc_stream_t *sock_stream; mongoc_stream_t *ssl_stream; mongoc_socket_t *conn_sock; int i; int errno_captured; char buf[1024]; ssize_t r; mongoc_iovec_t riov; mongoc_iovec_t wiov; mongoc_iovec_t wiov_many[NUM_IOVECS]; struct sockaddr_in server_addr = { 0 }; int len; riov.iov_base = buf; riov.iov_len = sizeof buf; conn_sock = mongoc_socket_new (AF_INET, SOCK_STREAM, 0); assert (conn_sock); mongoc_mutex_lock(&data->cond_mutex); while (! data->server_port) { mongoc_cond_wait(&data->cond, &data->cond_mutex); } mongoc_mutex_unlock(&data->cond_mutex); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(data->server_port); server_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); r = mongoc_socket_connect (conn_sock, (struct sockaddr *)&server_addr, sizeof(server_addr), -1); assert (r == 0); sock_stream = mongoc_stream_socket_new (conn_sock); assert(sock_stream); ssl_stream = mongoc_stream_tls_new(sock_stream, data->client, 1); if (! ssl_stream) { unsigned long err = ERR_get_error(); assert(err); data->client_result->ssl_err = err; data->client_result->result = SSL_TEST_SSL_INIT; mongoc_stream_destroy(sock_stream); return NULL; } assert(ssl_stream); errno = 0; r = mongoc_stream_tls_do_handshake (ssl_stream, TIMEOUT); errno_captured = errno; if (! r) { unsigned long err = ERR_get_error(); assert(err || errno_captured); if (err) { data->client_result->ssl_err = err; } else { data->client_result->err = errno_captured; } data->client_result->result = SSL_TEST_SSL_HANDSHAKE; mongoc_stream_destroy(ssl_stream); return NULL; } r = mongoc_stream_tls_check_cert (ssl_stream, data->host); if (! r) { data->client_result->result = SSL_TEST_SSL_VERIFY; mongoc_stream_destroy(ssl_stream); return NULL; } len = 4 * NUM_IOVECS; wiov.iov_base = (void *)&len; wiov.iov_len = 4; r = mongoc_stream_writev(ssl_stream, &wiov, 1, TIMEOUT); assert(r == wiov.iov_len); for (i = 0; i < NUM_IOVECS; i++) { wiov_many[i].iov_base = "foo"; wiov_many[i].iov_len = 4; } r = mongoc_stream_writev(ssl_stream, wiov_many, NUM_IOVECS, TIMEOUT); assert(r == wiov_many[0].iov_len * NUM_IOVECS); riov.iov_len = 1; r = mongoc_stream_readv(ssl_stream, &riov, 1, 1, TIMEOUT); assert(r == 1); assert(memcmp(riov.iov_base, "f", 1) == 0); riov.iov_len = 3; r = mongoc_stream_readv(ssl_stream, &riov, 1, 3, TIMEOUT); assert(r == 3); assert(memcmp(riov.iov_base, "oo", 3) == 0); mongoc_stream_destroy(ssl_stream); data->client_result->result = SSL_TEST_SUCCESS; return NULL; }
/** this function is meant to be run from ssl_test as a child thread * * It: * 1. spins up * 2. waits on a condvar until the server is up * 3. connects to the server's port * 4. writes a 4 bytes length * 5. writes a string of length size * 6. reads a response back of the given length * 7. confirms that its the same as what was written * 8. shuts down */ static void * ssl_test_client (void *ptr) { ssl_test_data_t *data = (ssl_test_data_t *) ptr; mongoc_stream_t *sock_stream; mongoc_stream_t *ssl_stream; mongoc_socket_t *conn_sock; int i; char buf[1024]; ssize_t r; mongoc_iovec_t riov; mongoc_iovec_t wiov; mongoc_iovec_t wiov_many[NUM_IOVECS]; struct sockaddr_in server_addr = {0}; int len; bson_error_t error; riov.iov_base = buf; riov.iov_len = sizeof buf; conn_sock = mongoc_socket_new (AF_INET, SOCK_STREAM, 0); BSON_ASSERT (conn_sock); mongoc_mutex_lock (&data->cond_mutex); while (!data->server_port) { mongoc_cond_wait (&data->cond, &data->cond_mutex); } mongoc_mutex_unlock (&data->cond_mutex); server_addr.sin_family = AF_INET; server_addr.sin_port = htons (data->server_port); server_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); r = mongoc_socket_connect ( conn_sock, (struct sockaddr *) &server_addr, sizeof (server_addr), -1); if (r != 0) { fprintf (stderr, "mongoc_socket_connect returned %zd: \"%s\"", r, strerror (errno)); abort (); } sock_stream = mongoc_stream_socket_new (conn_sock); BSON_ASSERT (sock_stream); ssl_stream = mongoc_stream_tls_new_with_hostname ( sock_stream, data->host, data->client, 1); if (!ssl_stream) { #ifdef MONGOC_ENABLE_SSL_OPENSSL unsigned long err = ERR_get_error (); #else unsigned long err = 44; #endif BSON_ASSERT (err); data->client_result->ssl_err = err; data->client_result->result = SSL_TEST_SSL_INIT; MONGOC_ERROR ("ERRORED (line: %d): %s\n", __LINE__, "mongoc_stream_tls_new_with_hostname failed."); mongoc_stream_destroy (sock_stream); return NULL; } BSON_ASSERT (ssl_stream); r = mongoc_stream_tls_handshake_block ( ssl_stream, data->host, TIMEOUT, &error); if (!r) { unsigned long err = 45; data->client_result->ssl_err = err; data->client_result->result = SSL_TEST_SSL_HANDSHAKE; MONGOC_ERROR ("ERRORED (line: %d): %s\n", __LINE__, error.message); mongoc_stream_destroy (ssl_stream); return NULL; } len = 4 * NUM_IOVECS; wiov.iov_base = (void *) &len; wiov.iov_len = 4; r = mongoc_stream_writev (ssl_stream, &wiov, 1, TIMEOUT); BSON_ASSERT (r == wiov.iov_len); for (i = 0; i < NUM_IOVECS; i++) { wiov_many[i].iov_base = (void *) "foo"; wiov_many[i].iov_len = 4; } r = mongoc_stream_writev (ssl_stream, wiov_many, NUM_IOVECS, TIMEOUT); BSON_ASSERT (r == wiov_many[0].iov_len * NUM_IOVECS); riov.iov_len = 1; r = mongoc_stream_readv (ssl_stream, &riov, 1, 1, TIMEOUT); BSON_ASSERT (r == 1); BSON_ASSERT (memcmp (riov.iov_base, "f", 1) == 0); riov.iov_len = 3; r = mongoc_stream_readv (ssl_stream, &riov, 1, 3, TIMEOUT); BSON_ASSERT (r == 3); BSON_ASSERT (memcmp (riov.iov_base, "oo", 3) == 0); mongoc_stream_destroy (ssl_stream); data->client_result->result = SSL_TEST_SUCCESS; return NULL; }
/** this function is meant to be run from ssl_test as a child thread * * It: * 1. spins up * 2. binds and listens to a random port * 3. notifies the client of its port through a condvar * 4. accepts a request * 5. reads a 32 bit length * 6. reads a string of that length * 7. echoes it back to the client * 8. shuts down */ static void * ssl_test_server (void *ptr) { ssl_test_data_t *data = (ssl_test_data_t *) ptr; mongoc_stream_t *sock_stream; mongoc_stream_t *ssl_stream; mongoc_socket_t *listen_sock; mongoc_socket_t *conn_sock; mongoc_socklen_t sock_len; char buf[4 * NUM_IOVECS]; ssize_t r; bson_error_t error; mongoc_iovec_t iov; struct sockaddr_in server_addr = {0}; int len; iov.iov_base = buf; iov.iov_len = sizeof buf; listen_sock = mongoc_socket_new (AF_INET, SOCK_STREAM, 0); BSON_ASSERT (listen_sock); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); server_addr.sin_port = htons (0); r = mongoc_socket_bind ( listen_sock, (struct sockaddr *) &server_addr, sizeof server_addr); BSON_ASSERT (r == 0); sock_len = sizeof (server_addr); r = mongoc_socket_getsockname ( listen_sock, (struct sockaddr *) &server_addr, &sock_len); BSON_ASSERT (r == 0); r = mongoc_socket_listen (listen_sock, 10); BSON_ASSERT (r == 0); mongoc_mutex_lock (&data->cond_mutex); data->server_port = ntohs (server_addr.sin_port); mongoc_cond_signal (&data->cond); mongoc_mutex_unlock (&data->cond_mutex); conn_sock = mongoc_socket_accept (listen_sock, -1); BSON_ASSERT (conn_sock); sock_stream = mongoc_stream_socket_new (conn_sock); BSON_ASSERT (sock_stream); ssl_stream = mongoc_stream_tls_new_with_hostname (sock_stream, NULL, data->server, 0); if (!ssl_stream) { #ifdef MONGOC_ENABLE_SSL_OPENSSL unsigned long err = ERR_get_error (); #else unsigned long err = 42; #endif BSON_ASSERT (err); data->server_result->ssl_err = err; data->server_result->result = SSL_TEST_SSL_INIT; #ifdef MONGOC_ENABLE_SSL_OPENSSL MONGOC_ERROR ("ERRORED (line: %d): %s\n", __LINE__, ERR_error_string (ERR_get_error (), NULL)); #endif mongoc_stream_destroy (sock_stream); mongoc_socket_destroy (listen_sock); return NULL; } BSON_ASSERT (ssl_stream); r = mongoc_stream_tls_handshake_block ( ssl_stream, data->host, TIMEOUT, &error); if (!r) { unsigned long err = 43; MONGOC_ERROR ("ERRORED (line: %d): %s\n", __LINE__, error.message); #ifdef MONGOC_ENABLE_SSL_OPENSSL MONGOC_ERROR ("msg: %s\n", ERR_error_string (ERR_get_error (), NULL)); #endif data->server_result->ssl_err = err; data->server_result->result = SSL_TEST_SSL_HANDSHAKE; mongoc_socket_destroy (listen_sock); mongoc_stream_destroy (ssl_stream); return NULL; } r = mongoc_stream_readv (ssl_stream, &iov, 1, 4, TIMEOUT); if (r < 0) { data->server_result->err = errno; data->server_result->result = SSL_TEST_TIMEOUT; MONGOC_ERROR ( "ERRORED (line: %d): %s\n", __LINE__, "mongoc_stream_readv failed."); mongoc_stream_destroy (ssl_stream); mongoc_socket_destroy (listen_sock); return NULL; } BSON_ASSERT (r == 4); memcpy (&len, iov.iov_base, r); r = mongoc_stream_readv (ssl_stream, &iov, 1, len, TIMEOUT); BSON_ASSERT (r == len); iov.iov_len = r; mongoc_stream_writev (ssl_stream, &iov, 1, TIMEOUT); mongoc_stream_destroy (ssl_stream); mongoc_socket_destroy (listen_sock); data->server_result->result = SSL_TEST_SUCCESS; return NULL; }
static void * socket_test_client (void *data_) { socket_test_data_t *data = (socket_test_data_t *)data_; mongoc_socket_t *conn_sock; char buf[5]; ssize_t r; bool closed; struct sockaddr_in server_addr = { 0 }; mongoc_stream_t *stream; mongoc_iovec_t iov; iov.iov_base = buf; iov.iov_len = sizeof (buf); conn_sock = mongoc_socket_new (AF_INET, SOCK_STREAM, 0); assert (conn_sock); mongoc_mutex_lock(&data->cond_mutex); while (! data->server_port) { mongoc_cond_wait(&data->cond, &data->cond_mutex); } mongoc_mutex_unlock(&data->cond_mutex); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(data->server_port); server_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); r = mongoc_socket_connect (conn_sock, (struct sockaddr *)&server_addr, sizeof(server_addr), -1); assert (r == 0); stream = mongoc_stream_socket_new (conn_sock); strcpy (buf, "ping"); closed = mongoc_stream_check_closed (stream); assert (closed == false); r = mongoc_stream_writev (stream, &iov, 1, TIMEOUT); assert (r == 5); closed = mongoc_stream_check_closed (stream); assert (closed == false); r = mongoc_stream_readv (stream, &iov, 1, 5, TIMEOUT); assert (r == 5); assert (strcmp (buf, "pong") == 0); mongoc_mutex_lock(&data->cond_mutex); while (! data->closed_socket) { mongoc_cond_wait(&data->cond, &data->cond_mutex); } mongoc_mutex_unlock(&data->cond_mutex); closed = mongoc_stream_check_closed (stream); assert (closed == true); mongoc_stream_destroy (stream); return NULL; }