static void test_mongoc_buffer_basic (void) { mongoc_stream_t *stream; mongoc_buffer_t buf; bson_uint8_t *data = bson_malloc0(1024); bson_error_t error = { 0 }; bson_bool_t r; int fd; fd = open("tests/binary/reply1.dat", O_RDONLY); assert(fd >= 0); stream = mongoc_stream_unix_new(fd); assert(stream); _mongoc_buffer_init(&buf, data, 1024, bson_realloc); r = _mongoc_buffer_fill(&buf, stream, 537, 0, &error); assert_cmpint(r, ==, -1); r = _mongoc_buffer_fill(&buf, stream, 536, 0, &error); assert_cmpint(r, ==, 536); assert(buf.len == 536); _mongoc_buffer_destroy(&buf); _mongoc_buffer_destroy(&buf); _mongoc_buffer_destroy(&buf); _mongoc_buffer_destroy(&buf); mongoc_stream_destroy(stream); }
static void test_mongoc_buffer_basic (void) { mongoc_stream_t *stream; mongoc_buffer_t buf; uint8_t *data = bson_malloc0(1024); bson_error_t error = { 0 }; ssize_t r; mongoc_fd_t fd; fd = mongoc_open("tests/binary/reply1.dat", O_RDONLY); ASSERT(mongoc_fd_is_valid(fd)); stream = mongoc_stream_unix_new(fd); ASSERT(stream); _mongoc_buffer_init(&buf, data, 1024, bson_realloc); r = _mongoc_buffer_fill(&buf, stream, 537, 0, &error); ASSERT_CMPINT((int)r, ==, -1); r = _mongoc_buffer_fill(&buf, stream, 536, 0, &error); ASSERT_CMPINT((int)r, ==, 536); ASSERT(buf.len == 536); _mongoc_buffer_destroy(&buf); _mongoc_buffer_destroy(&buf); _mongoc_buffer_destroy(&buf); _mongoc_buffer_destroy(&buf); mongoc_stream_destroy(stream); }
static ssize_t mongoc_stream_buffered_readv (mongoc_stream_t *stream, /* IN */ struct iovec *iov, /* INOUT */ size_t iovcnt, /* IN */ size_t min_bytes, /* IN */ int32_t timeout_msec) /* IN */ { mongoc_stream_buffered_t *buffered = (mongoc_stream_buffered_t *)stream; bson_error_t error = { 0 }; size_t total_bytes = 0; size_t i; bson_return_val_if_fail(buffered, -1); for (i = 0; i < iovcnt; i++) { total_bytes += iov[i].iov_len; } if (-1 == _mongoc_buffer_fill (&buffered->buffer, buffered->base_stream, total_bytes, timeout_msec, &error)) { MONGOC_WARNING ("Failure to buffer %u bytes: %s", (unsigned)total_bytes, error.message); return -1; } BSON_ASSERT(buffered->buffer.len >= total_bytes); for (i = 0; i < iovcnt; i++) { memcpy(iov[i].iov_base, buffered->buffer.data + buffered->buffer.off, iov[i].iov_len); buffered->buffer.off += iov[i].iov_len; buffered->buffer.len -= iov[i].iov_len; } return total_bytes; }
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; }
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); }