static int mongoc_stream_buffered_close (mongoc_stream_t *stream) /* IN */ { mongoc_stream_buffered_t *buffered = (mongoc_stream_buffered_t *)stream; bson_return_val_if_fail(stream, -1); return mongoc_stream_close(buffered->base_stream); }
static int _mongoc_stream_tls_close (mongoc_stream_t *stream) { mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *)stream; BSON_ASSERT (tls); return mongoc_stream_close (tls->base_stream); }
void mock_server_hangs_up (request_t *request) { test_suite_mock_server_log ("%5.2f %hu <- %hu \thang up!", mock_server_get_uptime_sec (request->server), request->client_port, request_get_server_port (request)); mongoc_stream_close (request->client); }
void mock_server_hangs_up (request_t *request) { if (mock_server_get_verbose (request->server)) { printf ("%5.2f %hu <- %hu \thang up!\n", mock_server_get_uptime_sec (request->server), request->client_port, request_get_server_port (request)); fflush (stdout); } mongoc_stream_close (request->client); }
static int _mongoc_stream_tls_secure_transport_close (mongoc_stream_t *stream) { int ret = 0; mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream; mongoc_stream_tls_secure_transport_t *secure_transport = (mongoc_stream_tls_secure_transport_t *) tls->ctx; ENTRY; BSON_ASSERT (secure_transport); ret = mongoc_stream_close (tls->base_stream); RETURN (ret); }
static void _mongoc_stream_gridfs_destroy (mongoc_stream_t *stream) { ENTRY; BSON_ASSERT (stream); mongoc_stream_close (stream); bson_free (stream); mongoc_counter_streams_active_dec (); mongoc_counter_streams_disposed_inc (); EXIT; }
static void mongoc_stream_unix_destroy (mongoc_stream_t *stream) { mongoc_stream_unix_t *file = (mongoc_stream_unix_t *)stream; bson_return_if_fail(stream); if (mongoc_stream_close(stream) != 0) { /* * TODO: Handle close failure. */ } file->fd = -1; bson_free(stream); }
void mock_server_resets (request_t *request) { struct linger no_linger; no_linger.l_onoff = 1; no_linger.l_linger = 0; test_suite_mock_server_log ("%5.2f %hu <- %hu \treset!", mock_server_get_uptime_sec (request->server), request->client_port, request_get_server_port (request)); /* send RST packet to client */ mongoc_stream_setsockopt (request->client, SOL_SOCKET, SO_LINGER, &no_linger, sizeof no_linger); mongoc_stream_close (request->client); }
void mock_server_resets (request_t *request) { struct linger no_linger; no_linger.l_onoff = 1; no_linger.l_linger = 0; if (mock_server_get_verbose (request->server)) { printf ("%5.2f %hu <- %hu \treset!\n", mock_server_get_uptime_sec (request->server), request->client_port, request_get_server_port (request)); fflush (stdout); } /* send RST packet to client */ mongoc_stream_setsockopt (request->client, SOL_SOCKET, SO_LINGER, &no_linger, sizeof no_linger); mongoc_stream_close (request->client); }
static void * mock_server_worker (void *data) { mongoc_buffer_t buffer; mongoc_stream_t *stream; mock_server_t *server; mongoc_rpc_t rpc; bson_error_t error; int32_t msg_len; void **closure = data; ENTRY; BSON_ASSERT(closure); server = closure[0]; stream = closure[1]; _mongoc_buffer_init(&buffer, NULL, 0, NULL, NULL); again: if (_mongoc_buffer_fill (&buffer, stream, 4, -1, &error) == -1) { MONGOC_WARNING ("%s():%d: %s", __FUNCTION__, __LINE__, error.message); GOTO (failure); } assert (buffer.len >= 4); memcpy (&msg_len, buffer.data + buffer.off, 4); msg_len = BSON_UINT32_FROM_LE (msg_len); if (msg_len < 16) { MONGOC_WARNING ("No data"); GOTO (failure); } if (_mongoc_buffer_fill (&buffer, stream, msg_len, -1, &error) == -1) { MONGOC_WARNING ("%s():%d: %s", __FUNCTION__, __LINE__, error.message); GOTO (failure); } assert (buffer.len >= (unsigned)msg_len); DUMP_BYTES (buffer, buffer.data + buffer.off, buffer.len); if (!_mongoc_rpc_scatter(&rpc, buffer.data + buffer.off, msg_len)) { MONGOC_WARNING ("%s():%d: %s", __FUNCTION__, __LINE__, "Failed to scatter"); GOTO (failure); } _mongoc_rpc_swab_from_le(&rpc); if (!handle_command(server, stream, &rpc)) { server->handler(server, stream, &rpc, server->handler_data); } memmove (buffer.data, buffer.data + buffer.off + msg_len, buffer.len - msg_len); buffer.off = 0; buffer.len -= msg_len; GOTO (again); failure: mongoc_stream_close (stream); mongoc_stream_destroy (stream); bson_free(closure); _mongoc_buffer_destroy (&buffer); RETURN (NULL); }
/* TODO: factor */ static void * worker_thread (void *data) { worker_closure_t *closure = (worker_closure_t *) data; mock_server_t *server = closure->server; mongoc_stream_t *client_stream = closure->client_stream; mongoc_buffer_t buffer; mongoc_rpc_t *rpc = NULL; bool handled; bson_error_t error; int32_t msg_len; bool stopped; sync_queue_t *q; request_t *request; mongoc_array_t autoresponders; ssize_t i; autoresponder_handle_t handle; #ifdef MONGOC_ENABLE_SSL bool ssl; #endif ENTRY; BSON_ASSERT(closure); #ifdef MONGOC_ENABLE_SSL mongoc_mutex_lock (&server->mutex); ssl = server->ssl; mongoc_mutex_unlock (&server->mutex); if (ssl) { if (!mongoc_stream_tls_handshake_block (client_stream, "localhost", TIMEOUT, &error)) { MONGOC_ERROR("Blocking TLS handshake failed"); mongoc_stream_close (client_stream); mongoc_stream_destroy (client_stream); RETURN (NULL); } } #endif _mongoc_buffer_init (&buffer, NULL, 0, NULL, NULL); _mongoc_array_init (&autoresponders, sizeof (autoresponder_handle_t)); again: bson_free (rpc); rpc = NULL; handled = false; mongoc_mutex_lock (&server->mutex); stopped = server->stopped; mongoc_mutex_unlock (&server->mutex); if (stopped) { GOTO(failure); } if (_mongoc_buffer_fill (&buffer, client_stream, 4, TIMEOUT, &error) == -1) { GOTO (again); } assert (buffer.len >= 4); memcpy (&msg_len, buffer.data + buffer.off, 4); msg_len = BSON_UINT32_FROM_LE (msg_len); if (msg_len < 16) { MONGOC_WARNING ("No data"); GOTO (failure); } if (_mongoc_buffer_fill (&buffer, client_stream, (size_t) msg_len, -1, &error) == -1) { MONGOC_WARNING ("%s():%d: %s", BSON_FUNC, __LINE__, error.message); GOTO (failure); } assert (buffer.len >= (unsigned) msg_len); /* copies message from buffer */ request = request_new (&buffer, msg_len, server, client_stream, closure->port); mongoc_mutex_lock (&server->mutex); _mongoc_array_copy (&autoresponders, &server->autoresponders); mongoc_mutex_unlock (&server->mutex); if (mock_server_get_verbose (server)) { printf ("%5.2f %hu -> %hu %s\n", mock_server_get_uptime_sec (server), closure->port, server->port, request->as_str); fflush (stdout); } /* run responders most-recently-added-first */ for (i = server->autoresponders.len - 1; i >= 0; i--) { handle = _mongoc_array_index (&server->autoresponders, autoresponder_handle_t, i); if (handle.responder (request, handle.data)) { handled = true; /* responder should destroy the request */ request = NULL; break; } } if (!handled) { q = mock_server_get_queue (server); q_put (q, (void *) request); request = NULL; } memmove (buffer.data, buffer.data + buffer.off + msg_len, buffer.len - msg_len); buffer.off = 0; buffer.len -= msg_len; GOTO (again); failure: _mongoc_array_destroy (&autoresponders); _mongoc_buffer_destroy (&buffer); mongoc_stream_close (client_stream); mongoc_stream_destroy (client_stream); bson_free (rpc); bson_free (closure); _mongoc_buffer_destroy (&buffer); RETURN (NULL); }
static void * mock_server_worker (void *data) { mongoc_buffer_t buffer; mongoc_stream_t *stream; mock_server_t *server; mongoc_rpc_t rpc; bson_error_t error; int32_t msg_len; void **closure = data; BSON_ASSERT(closure); server = closure[0]; stream = closure[1]; _mongoc_buffer_init(&buffer, NULL, 0, NULL); again: if (_mongoc_buffer_fill (&buffer, stream, 4, INT_MAX, &error) == -1) { MONGOC_WARNING ("%s", error.message); goto failure; } assert (buffer.len >= 4); memcpy(&msg_len, buffer.data + buffer.off, 4); msg_len = BSON_UINT32_FROM_LE(msg_len); if (msg_len < 16) { MONGOC_WARNING ("No data"); goto failure; } if (_mongoc_buffer_fill (&buffer, stream, msg_len, INT_MAX, &error) == -1) { MONGOC_WARNING ("%s", error.message); goto failure; } assert (buffer.len >= msg_len); DUMP_BYTES (buffer, buffer.data + buffer.off, buffer.len); if (!_mongoc_rpc_scatter(&rpc, buffer.data + buffer.off, msg_len)) { MONGOC_WARNING ("Failed to scatter"); goto failure; } _mongoc_rpc_swab_from_le(&rpc); if (!handle_command(server, stream, &rpc)) { server->handler(server, stream, &rpc, server->handler_data); } memmove (buffer.data, buffer.data + buffer.off + msg_len, buffer.len - msg_len); buffer.off = 0; buffer.len -= msg_len; goto again; failure: mongoc_stream_close(stream); mongoc_stream_destroy(stream); bson_free(closure); 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; }
static void * worker_thread (void *data) { worker_closure_t *closure = (worker_closure_t *) data; mock_server_t *server = closure->server; mongoc_stream_t *client_stream = closure->client_stream; mongoc_buffer_t buffer; mongoc_rpc_t *rpc = NULL; bool handled; bson_error_t error; int32_t msg_len; sync_queue_t *requests; sync_queue_t *replies; request_t *request; mongoc_array_t autoresponders; ssize_t i; autoresponder_handle_t handle; reply_t *reply; #ifdef MONGOC_ENABLE_SSL bool ssl; #endif ENTRY; /* queue of client replies sent over this worker's connection */ replies = q_new (); #ifdef MONGOC_ENABLE_SSL mongoc_mutex_lock (&server->mutex); ssl = server->ssl; mongoc_mutex_unlock (&server->mutex); if (ssl) { if (!mongoc_stream_tls_handshake_block (client_stream, "localhost", TIMEOUT, &error)) { mongoc_stream_close (client_stream); mongoc_stream_destroy (client_stream); RETURN (NULL); } } #endif _mongoc_buffer_init (&buffer, NULL, 0, NULL, NULL); _mongoc_array_init (&autoresponders, sizeof (autoresponder_handle_t)); again: /* loop, checking for requests to receive or replies to send */ bson_free (rpc); rpc = NULL; if (_mongoc_buffer_fill (&buffer, client_stream, 4, 10, &error) > 0) { assert (buffer.len >= 4); memcpy (&msg_len, buffer.data + buffer.off, 4); msg_len = BSON_UINT32_FROM_LE (msg_len); if (msg_len < 16) { MONGOC_WARNING ("No data"); GOTO (failure); } if (_mongoc_buffer_fill (&buffer, client_stream, (size_t) msg_len, -1, &error) == -1) { MONGOC_WARNING ("%s():%d: %s", BSON_FUNC, __LINE__, error.message); GOTO (failure); } assert (buffer.len >= (unsigned) msg_len); /* copies message from buffer */ request = request_new (&buffer, msg_len, server, client_stream, closure->port, replies); memmove (buffer.data, buffer.data + buffer.off + msg_len, buffer.len - msg_len); buffer.off = 0; buffer.len -= msg_len; mongoc_mutex_lock (&server->mutex); _mongoc_array_copy (&autoresponders, &server->autoresponders); mongoc_mutex_unlock (&server->mutex); test_suite_mock_server_log ("%5.2f %hu -> %hu %s", mock_server_get_uptime_sec (server), closure->port, server->port, request->as_str); /* run responders most-recently-added-first */ handled = false; for (i = server->autoresponders.len - 1; i >= 0; i--) { handle = _mongoc_array_index (&server->autoresponders, autoresponder_handle_t, i); if (handle.responder (request, handle.data)) { /* responder destroyed request and enqueued a reply in "replies" */ handled = true; request = NULL; break; } } if (!handled) { /* pass to the main thread via the queue */ requests = mock_server_get_queue (server); q_put (requests, (void *) request); } } if (_mock_server_stopping (server)) { GOTO (failure); } reply = q_get (replies, 10); if (reply) { _mock_server_reply_with_stream (server, reply, client_stream); _reply_destroy (reply); } if (_mock_server_stopping (server)) { GOTO (failure); } GOTO (again); failure: _mongoc_array_destroy (&autoresponders); _mongoc_buffer_destroy (&buffer); mongoc_stream_close (client_stream); mongoc_stream_destroy (client_stream); bson_free (rpc); bson_free (closure); _mongoc_buffer_destroy (&buffer); while ((reply = q_get_nowait (replies))) { _reply_destroy (reply); } q_destroy (replies); RETURN (NULL); }
static int _mongoc_stream_debug_close (mongoc_stream_t *stream) { return mongoc_stream_close (((mongoc_stream_debug_t *) stream)->wrapped); }
int main (int argc, char *argv[]) { const char *uri_string = "mongodb://localhost:27017/?appname=new-gridfs-example"; mongoc_client_t *client; mongoc_database_t *db; mongoc_stream_t *file_stream; mongoc_gridfs_bucket_t *bucket; mongoc_cursor_t *cursor; bson_t filter; bool res; bson_value_t file_id; bson_error_t error; const bson_t *doc; char *str; mongoc_init (); if (argc != 3) { fprintf (stderr, "usage: %s SOURCE_FILE_PATH FILE_COPY_PATH\n", argv[0]); return EXIT_FAILURE; } /* 1. Make a bucket. */ client = mongoc_client_new (uri_string); db = mongoc_client_get_database (client, "test"); bucket = mongoc_gridfs_bucket_new (db, NULL, NULL); /* 2. Insert a file. */ file_stream = mongoc_stream_file_new_for_path (argv[1], O_RDONLY, 0); res = mongoc_gridfs_bucket_upload_from_stream ( bucket, "my-file", file_stream, NULL, &file_id, &error); if (!res) { printf ("Error uploading file: %s\n", error.message); return EXIT_FAILURE; } mongoc_stream_close (file_stream); mongoc_stream_destroy (file_stream); /* 3. Download the file in GridFS to a local file. */ file_stream = mongoc_stream_file_new_for_path (argv[2], O_CREAT | O_RDWR, 0); if (!file_stream) { perror ("Error opening file stream"); return EXIT_FAILURE; } res = mongoc_gridfs_bucket_download_to_stream ( bucket, &file_id, file_stream, &error); if (!res) { printf ("Error downloading file to stream: %s\n", error.message); return EXIT_FAILURE; } mongoc_stream_close (file_stream); mongoc_stream_destroy (file_stream); /* 4. List what files are available in GridFS. */ bson_init (&filter); cursor = mongoc_gridfs_bucket_find (bucket, &filter, NULL); while (mongoc_cursor_next (cursor, &doc)) { str = bson_as_canonical_extended_json (doc, NULL); printf ("%s\n", str); bson_free (str); } /* 5. Delete the file that we added. */ res = mongoc_gridfs_bucket_delete_by_id (bucket, &file_id, &error); if (!res) { printf ("Error deleting the file: %s\n", error.message); return EXIT_FAILURE; } /* 6. Cleanup. */ mongoc_stream_close (file_stream); mongoc_stream_destroy (file_stream); mongoc_cursor_destroy (cursor); bson_destroy (&filter); mongoc_gridfs_bucket_destroy (bucket); mongoc_database_destroy (db); mongoc_client_destroy (client); mongoc_cleanup (); return EXIT_SUCCESS; }