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); }
static void validate (const char *name) /* IN */ { mongoc_stream_t *stream; mongoc_rpc_t rpc; #ifdef _WIN32 struct _stat st; #else struct stat st; #endif uint8_t *buf; int32_t len; int ret; stream = mongoc_stream_file_new_for_path (name, O_RDONLY, 0); if (!stream) { perror ("failed to open file"); exit (EXIT_FAILURE); } #ifdef _WIN32 ret = _stat (name, &st); #else ret = stat (name, &st); #endif if (ret != 0) { perror ("failed to stat() file."); exit (EXIT_FAILURE); } if ((st.st_size > (100 * 1024 * 1024)) || (st.st_size < 16)) { fprintf (stderr, "%s: unreasonable message size\n", name); exit (EXIT_FAILURE); } buf = malloc (st.st_size); if (buf == NULL) { fprintf (stderr, "%s: Failed to malloc %d bytes.\n", name, (int)st.st_size); exit (EXIT_FAILURE); } if (st.st_size != mongoc_stream_read (stream, buf, st.st_size, st.st_size, -1)) { fprintf (stderr, "%s: Failed to read %d bytes into buffer.\n", name, (int)st.st_size); exit (EXIT_FAILURE); } memcpy (&len, buf, 4); len = BSON_UINT32_FROM_LE (len); if (len != st.st_size) { fprintf (stderr, "%s is invalid. Invalid Length.\n", name); exit (EXIT_FAILURE); } if (!_mongoc_rpc_scatter (&rpc, buf, st.st_size)) { fprintf (stderr, "%s is invalid. Invalid Format.\n", name); exit (EXIT_FAILURE); } fprintf (stdout, "%s is valid.\n", name); bson_free (buf); }
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; }
mongoc_async_cmd_result_t _mongoc_async_cmd_phase_recv_rpc (mongoc_async_cmd_t *acmd) { ssize_t bytes = _mongoc_buffer_try_append_from_stream ( &acmd->buffer, acmd->stream, acmd->bytes_to_read, 0); if (bytes <= 0 && mongoc_stream_should_retry (acmd->stream)) { return MONGOC_ASYNC_CMD_IN_PROGRESS; } if (bytes < 0) { bson_set_error (&acmd->error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "Failed to receive rpc bytes from server."); return MONGOC_ASYNC_CMD_ERROR; } if (bytes == 0) { bson_set_error (&acmd->error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "Server closed connection."); return MONGOC_ASYNC_CMD_ERROR; } acmd->bytes_to_read = (size_t) (acmd->bytes_to_read - bytes); if (!acmd->bytes_to_read) { if (!_mongoc_rpc_scatter ( &acmd->rpc, acmd->buffer.data, acmd->buffer.len)) { bson_set_error (&acmd->error, MONGOC_ERROR_PROTOCOL, MONGOC_ERROR_PROTOCOL_INVALID_REPLY, "Invalid reply from server."); return MONGOC_ASYNC_CMD_ERROR; } if (BSON_UINT32_FROM_LE (acmd->rpc.header.opcode) == MONGOC_OPCODE_COMPRESSED) { uint8_t *buf = NULL; size_t len = BSON_UINT32_FROM_LE (acmd->rpc.compressed.uncompressed_size) + sizeof (mongoc_rpc_header_t); buf = bson_malloc0 (len); if (!_mongoc_rpc_decompress (&acmd->rpc, buf, len)) { bson_free (buf); bson_set_error (&acmd->error, MONGOC_ERROR_PROTOCOL, MONGOC_ERROR_PROTOCOL_INVALID_REPLY, "Could not decompress server reply"); return MONGOC_ASYNC_CMD_ERROR; } _mongoc_buffer_destroy (&acmd->buffer); _mongoc_buffer_init (&acmd->buffer, buf, len, NULL, NULL); } _mongoc_rpc_swab_from_le (&acmd->rpc); if (!_mongoc_rpc_get_first_document (&acmd->rpc, &acmd->reply)) { bson_set_error (&acmd->error, MONGOC_ERROR_PROTOCOL, MONGOC_ERROR_PROTOCOL_INVALID_REPLY, "Invalid reply from server"); return MONGOC_ASYNC_CMD_ERROR; } acmd->reply_needs_cleanup = true; return MONGOC_ASYNC_CMD_SUCCESS; } return MONGOC_ASYNC_CMD_IN_PROGRESS; }