bson_bool_t _mongoc_sasl_step (mongoc_sasl_t *sasl, const bson_uint8_t *inbuf, bson_uint32_t inbuflen, bson_uint8_t *outbuf, bson_uint32_t outbufmax, bson_uint32_t *outbuflen, bson_error_t *error) { const char *raw = NULL; unsigned rawlen = 0; int status; BSON_ASSERT (sasl); BSON_ASSERT (inbuf); BSON_ASSERT (outbuf); BSON_ASSERT (outbuflen); BSON_ASSERT (*outbuflen); sasl->step++; if (sasl->step == 1) { return _mongoc_sasl_start (sasl, outbuf, outbufmax, outbuflen, error); } else if (sasl->step >= 10) { bson_set_error (error, MONGOC_ERROR_SASL, SASL_NOTDONE, "SASL Failure: maximum steps detected"); return FALSE; } if (!inbuflen) { bson_set_error (error, MONGOC_ERROR_SASL, MONGOC_ERROR_CLIENT_AUTHENTICATE, "SASL Failure: no payload provided from server."); return FALSE; } status = sasl_decode64 ((char *)inbuf, inbuflen, (char *)outbuf, outbufmax, outbuflen); if (_mongoc_sasl_is_failure (status, error)) { return FALSE; } status = sasl_client_step (sasl->conn, (char *)outbuf, *outbuflen, &sasl->interact, &raw, &rawlen); if (_mongoc_sasl_is_failure (status, error)) { return FALSE; } status = sasl_encode64 (raw, rawlen, (char *)outbuf, outbufmax, outbuflen); if (_mongoc_sasl_is_failure (status, error)) { return FALSE; } return TRUE; }
static bool _mongoc_cursor_unwrap_failure (mongoc_cursor_t *cursor) { bson_iter_t iter; bson_t b; ENTRY; bson_return_val_if_fail(cursor, false); if (cursor->rpc.header.opcode != MONGOC_OPCODE_REPLY) { bson_set_error(&cursor->error, MONGOC_ERROR_PROTOCOL, MONGOC_ERROR_PROTOCOL_INVALID_REPLY, "Received rpc other than OP_REPLY."); RETURN(true); } if ((cursor->rpc.reply.flags & MONGOC_REPLY_QUERY_FAILURE)) { if (_mongoc_rpc_reply_get_first(&cursor->rpc.reply, &b)) { _mongoc_cursor_populate_error(cursor, &b, &cursor->error); bson_destroy(&b); } else { bson_set_error(&cursor->error, MONGOC_ERROR_QUERY, MONGOC_ERROR_QUERY_FAILURE, "Unknown query failure."); } RETURN(true); } else if (cursor->is_command) { if (_mongoc_rpc_reply_get_first (&cursor->rpc.reply, &b)) { if (bson_iter_init_find (&iter, &b, "ok")) { if (bson_iter_as_bool (&iter)) { RETURN (false); } else { _mongoc_cursor_populate_error (cursor, &b, &cursor->error); bson_destroy (&b); RETURN (true); } } } else { bson_set_error (&cursor->error, MONGOC_ERROR_BSON, MONGOC_ERROR_BSON_INVALID, "Failed to decode document from the server."); RETURN (true); } } if ((cursor->rpc.reply.flags & MONGOC_REPLY_CURSOR_NOT_FOUND)) { bson_set_error(&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "The cursor is invalid or has expired."); RETURN(true); } RETURN(false); }
/* returns true if the reply is a server error */ static bool _mongoc_rpc_parse_error (mongoc_rpc_t *rpc, bool is_command, int32_t error_api_version, bson_error_t *error /* OUT */) { bson_t b; bool r; ENTRY; BSON_ASSERT (rpc); if (rpc->header.opcode != MONGOC_OPCODE_REPLY) { bson_set_error(error, MONGOC_ERROR_PROTOCOL, MONGOC_ERROR_PROTOCOL_INVALID_REPLY, "Received rpc other than OP_REPLY."); RETURN(true); } if (is_command) { if (_mongoc_rpc_reply_get_first (&rpc->reply, &b)) { r = _mongoc_populate_cmd_error (&b, error_api_version, error); bson_destroy(&b); RETURN (r); } else { bson_set_error (error, MONGOC_ERROR_BSON, MONGOC_ERROR_BSON_INVALID, "Failed to decode document from the server."); RETURN (true); } } else if ((rpc->reply.flags & MONGOC_REPLY_QUERY_FAILURE)) { if (_mongoc_rpc_reply_get_first (&rpc->reply, &b)) { _mongoc_populate_query_error (&b, error_api_version, error); bson_destroy (&b); } else { bson_set_error (error, MONGOC_ERROR_QUERY, MONGOC_ERROR_QUERY_FAILURE, "Unknown query failure."); } RETURN (true); } if ((rpc->reply.flags & MONGOC_REPLY_CURSOR_NOT_FOUND)) { bson_set_error(error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "The cursor is invalid or has expired."); RETURN(true); } RETURN(false); }
static bool _mongoc_cyrus_is_failure (int status, bson_error_t *error) { bool ret = (status < 0); TRACE ("Got status: %d ok is %d, continue=%d interact=%d\n", status, SASL_OK, SASL_CONTINUE, SASL_INTERACT); if (ret) { switch (status) { case SASL_NOMEM: bson_set_error (error, MONGOC_ERROR_SASL, status, "SASL Failure: insufficient memory."); break; case SASL_NOMECH: { bson_string_t *str = bson_string_new ("available mechanisms: "); const char **mechs = sasl_global_listmech (); int i = 0; for (i = 0; mechs[i]; i++) { bson_string_append (str, mechs[i]); if (mechs[i + 1]) { bson_string_append (str, ","); } } bson_set_error (error, MONGOC_ERROR_SASL, status, "SASL Failure: failure to negotiate mechanism (%s)", str->str); bson_string_free (str, 0); } break; case SASL_BADPARAM: bson_set_error (error, MONGOC_ERROR_SASL, status, "Bad parameter supplied. Please file a bug " "with mongo-c-driver."); break; default: bson_set_error (error, MONGOC_ERROR_SASL, status, "SASL Failure: (%d): %s", status, sasl_errstring (status, NULL, NULL)); break; } } return ret; }
static mongoc_stream_t * mongoc_client_connect_unix (const mongoc_uri_t *uri, const mongoc_host_list_t *host, bson_error_t *error) { #ifdef _WIN32 ENTRY; bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_CONNECT, "UNIX domain sockets not supported on win32."); RETURN (NULL); #else struct sockaddr_un saddr; mongoc_socket_t *sock; mongoc_stream_t *ret = NULL; ENTRY; bson_return_val_if_fail (uri, NULL); bson_return_val_if_fail (host, NULL); memset (&saddr, 0, sizeof saddr); saddr.sun_family = AF_UNIX; bson_snprintf (saddr.sun_path, sizeof saddr.sun_path - 1, "%s", host->host_and_port); sock = mongoc_socket_new (AF_UNIX, SOCK_STREAM, 0); if (sock == NULL) { bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "Failed to create socket."); RETURN (NULL); } if (-1 == mongoc_socket_connect (sock, (struct sockaddr *)&saddr, sizeof saddr, -1)) { mongoc_socket_destroy (sock); bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_CONNECT, "Failed to connect to UNIX domain socket."); RETURN (NULL); } ret = mongoc_stream_socket_new (sock); RETURN (ret); #endif }
bool _mongoc_stream_writev_full (mongoc_stream_t *stream, mongoc_iovec_t *iov, size_t iovcnt, int32_t timeout_msec, bson_error_t *error) { size_t total_bytes = 0; int i; ssize_t r; ENTRY; for (i = 0; i < iovcnt; i++) { total_bytes += iov[i].iov_len; } r = mongoc_stream_writev (stream, iov, iovcnt, timeout_msec); TRACE ("writev returned: %ld", r); if (r < 0) { if (error) { char buf[128]; char *errstr; errstr = bson_strerror_r (errno, buf, sizeof (buf)); bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "Failure during socket delivery: %s (%d)", errstr, errno); } RETURN (false); } if (r != total_bytes) { bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "Failure to send all requested bytes (only sent: %" PRIu64 "/%" PRId64 " in %dms) during socket delivery", (uint64_t) r, (int64_t) total_bytes, timeout_msec); RETURN (false); } RETURN (true); }
mongoc_async_cmd_result_t _mongoc_async_cmd_phase_recv_len (mongoc_async_cmd_t *acmd) { ssize_t bytes = _mongoc_buffer_try_append_from_stream ( &acmd->buffer, acmd->stream, acmd->bytes_to_read, 0); uint32_t msg_len; 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 length header 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) { memcpy (&msg_len, acmd->buffer.data, 4); msg_len = BSON_UINT32_FROM_LE (msg_len); if (msg_len < 16 || msg_len > MONGOC_DEFAULT_MAX_MSG_SIZE || msg_len < 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; } acmd->bytes_to_read = msg_len - acmd->buffer.len; acmd->state = MONGOC_ASYNC_CMD_RECV_RPC; return _mongoc_async_cmd_phase_recv_rpc (acmd); } return MONGOC_ASYNC_CMD_IN_PROGRESS; }
mongoc_cursor_t * _mongoc_cursor_cmd_new_from_reply (mongoc_client_t *client, const bson_t *cmd, const bson_t *opts, bson_t *reply) { mongoc_cursor_t *cursor = _mongoc_cursor_cmd_new (client, NULL, cmd, opts, NULL, NULL, NULL); data_cmd_t *data = (data_cmd_t *) cursor->impl.data; data->reading_from = CMD_RESPONSE; cursor->state = IN_BATCH; bson_destroy (&data->response.reply); if (!bson_steal (&data->response.reply, reply)) { bson_destroy (&data->response.reply); BSON_ASSERT (bson_steal (&data->response.reply, bson_copy (reply))); } if (!_mongoc_cursor_start_reading_response (cursor, &data->response)) { bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "Couldn't parse cursor document"); } return cursor; }
static void _mongoc_populate_query_error (const bson_t *doc, int32_t error_api_version, bson_error_t *error) { mongoc_error_domain_t domain = error_api_version >= MONGOC_ERROR_API_VERSION_2 ? MONGOC_ERROR_SERVER : MONGOC_ERROR_QUERY; uint32_t code = MONGOC_ERROR_QUERY_FAILURE; bson_iter_t iter; const char *msg = "Unknown query failure"; ENTRY; BSON_ASSERT (doc); if (bson_iter_init_find (&iter, doc, "code") && BSON_ITER_HOLDS_INT32 (&iter)) { code = (uint32_t) bson_iter_int32 (&iter); } if (bson_iter_init_find (&iter, doc, "$err") && BSON_ITER_HOLDS_UTF8 (&iter)) { msg = bson_iter_utf8 (&iter, NULL); } bson_set_error (error, domain, code, "%s", msg); EXIT; }
void _mongoc_cursor_cursorid_init_with_reply (mongoc_cursor_t *cursor, bson_t *reply, uint32_t server_id) { mongoc_cursor_cursorid_t *cid; cursor->sent = true; cursor->server_id = server_id; cid = (mongoc_cursor_cursorid_t *)cursor->iface_data; BSON_ASSERT (cid); bson_destroy (&cid->array); if (!bson_steal (&cid->array, reply)) { bson_steal (&cid->array, bson_copy (reply)); } if (!_mongoc_cursor_cursorid_start_batch (cursor)) { bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "Couldn't parse cursor document"); } }
bson_reader_t * bson_reader_new_from_file (const char *path, /* IN */ bson_error_t *error) /* OUT */ { char errmsg[32]; int fd; bson_return_val_if_fail (path, NULL); #ifdef BSON_OS_WIN32 fd = _open (path, (_O_RDONLY | _O_BINARY)); #else fd = open (path, O_RDONLY); #endif if (fd == -1) { bson_strerror_r (errno, errmsg, sizeof errmsg); bson_set_error (error, BSON_ERROR_READER, BSON_ERROR_READER_BADFD, "%s", errmsg); return NULL; } return bson_reader_new_from_fd (fd, true); }
bson_reader_t * bson_reader_new_from_file (const char *path, /* IN */ bson_error_t *error) /* OUT */ { char errmsg_buf[BSON_ERROR_BUFFER_SIZE]; char *errmsg; int fd; bson_return_val_if_fail (path, NULL); #ifdef BSON_OS_WIN32 if (_sopen_s (&fd, path, (_O_RDONLY | _O_BINARY), _SH_DENYNO, 0) != 0) { fd = -1; } #else fd = open (path, O_RDONLY); #endif if (fd == -1) { errmsg = bson_strerror_r (errno, errmsg_buf, sizeof errmsg_buf); bson_set_error (error, BSON_ERROR_READER, BSON_ERROR_READER_BADFD, "%s", errmsg); return NULL; } return bson_reader_new_from_fd (fd, true); }
static void _mongoc_cursor_populate_error (mongoc_cursor_t *cursor, const bson_t *doc, bson_error_t *error) { bson_uint32_t code = MONGOC_ERROR_QUERY_FAILURE; bson_iter_t iter; const char *msg = "Unknown query failure"; BSON_ASSERT (cursor); BSON_ASSERT (doc); BSON_ASSERT (error); if (bson_iter_init_find (&iter, doc, "code") && BSON_ITER_HOLDS_INT32 (&iter)) { code = bson_iter_int32 (&iter); } if (bson_iter_init_find (&iter, doc, "$err") && BSON_ITER_HOLDS_UTF8 (&iter)) { msg = bson_iter_utf8 (&iter, NULL); } if (cursor->is_command && bson_iter_init_find (&iter, doc, "errmsg") && BSON_ITER_HOLDS_UTF8 (&iter)) { msg = bson_iter_utf8 (&iter, NULL); } bson_set_error(error, MONGOC_ERROR_QUERY, code, "%s", msg); }
/* * If error is not set, set code from first document in array like * [{"code": 64, "errmsg": "duplicate"}, ...]. Format the error message * from all errors in array. */ static void _set_error_from_response (bson_t *bson_array, mongoc_error_domain_t domain, const char *error_type, bson_error_t *error /* OUT */) { bson_iter_t array_iter; bson_iter_t doc_iter; bson_string_t *compound_err; const char *errmsg = NULL; int32_t code = 0; uint32_t n_keys, i; compound_err = bson_string_new (NULL); n_keys = bson_count_keys (bson_array); if (n_keys > 1) { bson_string_append_printf ( compound_err, "Multiple %s errors: ", error_type); } if (!bson_empty0 (bson_array) && bson_iter_init (&array_iter, bson_array)) { /* get first code and all error messages */ i = 0; while (bson_iter_next (&array_iter)) { if (BSON_ITER_HOLDS_DOCUMENT (&array_iter) && bson_iter_recurse (&array_iter, &doc_iter)) { /* parse doc, which is like {"code": 64, "errmsg": "duplicate"} */ while (bson_iter_next (&doc_iter)) { /* use the first error code we find */ if (BSON_ITER_IS_KEY (&doc_iter, "code") && code == 0) { code = bson_iter_int32 (&doc_iter); } else if (BSON_ITER_IS_KEY (&doc_iter, "errmsg")) { errmsg = bson_iter_utf8 (&doc_iter, NULL); /* build message like 'Multiple write errors: "foo", "bar"' */ if (n_keys > 1) { bson_string_append_printf (compound_err, "\"%s\"", errmsg); if (i < n_keys - 1) { bson_string_append (compound_err, ", "); } } else { /* single error message */ bson_string_append (compound_err, errmsg); } } } i++; } } if (code && compound_err->len) { bson_set_error ( error, domain, (uint32_t) code, "%s", compound_err->str); } } bson_string_free (compound_err, true); }
bool _mongoc_scram_step (mongoc_scram_t *scram, const uint8_t *inbuf, uint32_t inbuflen, uint8_t *outbuf, uint32_t outbufmax, uint32_t *outbuflen, bson_error_t *error) { BSON_ASSERT (scram); BSON_ASSERT (inbuf); BSON_ASSERT (outbuf); BSON_ASSERT (outbuflen); scram->step++; switch (scram->step) { case 1: return _mongoc_scram_start (scram, outbuf, outbufmax, outbuflen, error); case 2: return _mongoc_scram_step2 ( scram, inbuf, inbuflen, outbuf, outbufmax, outbuflen, error); case 3: return _mongoc_scram_step3 ( scram, inbuf, inbuflen, outbuf, outbufmax, outbuflen, error); default: bson_set_error (error, MONGOC_ERROR_SCRAM, MONGOC_ERROR_SCRAM_NOT_DONE, "SCRAM Failure: maximum steps detected"); return false; } }
static bool _mongoc_cursor_cursorid_refresh_from_command (mongoc_cursor_t *cursor, const bson_t *command) { mongoc_cursor_cursorid_t *cid; ENTRY; cid = (mongoc_cursor_cursorid_t *)cursor->iface_data; BSON_ASSERT (cid); bson_destroy (&cid->array); /* server replies to find / aggregate with {cursor: {id: N, firstBatch: []}}, * to getMore command with {cursor: {id: N, nextBatch: []}}. */ if (_mongoc_cursor_run_command (cursor, command, &cid->array) && _mongoc_cursor_cursorid_start_batch (cursor)) { RETURN (true); } else { if (!cursor->error.domain) { bson_set_error (&cursor->error, MONGOC_ERROR_PROTOCOL, MONGOC_ERROR_PROTOCOL_INVALID_REPLY, "Invalid reply to %s command.", _mongoc_get_command_name (command)); } RETURN (false); } }
uint32_t _mongoc_client_sendv (mongoc_client_t *client, mongoc_rpc_t *rpcs, size_t rpcs_len, uint32_t hint, const mongoc_write_concern_t *write_concern, const mongoc_read_prefs_t *read_prefs, bson_error_t *error) { size_t i; bson_return_val_if_fail(client, false); bson_return_val_if_fail(rpcs, false); bson_return_val_if_fail(rpcs_len, false); if (client->in_exhaust) { bson_set_error(error, MONGOC_ERROR_CLIENT, MONGOC_ERROR_CLIENT_IN_EXHAUST, "A cursor derived from this client is in exhaust."); RETURN(false); } for (i = 0; i < rpcs_len; i++) { rpcs[i].header.msg_len = 0; rpcs[i].header.request_id = ++client->request_id; } switch (client->cluster.state) { case MONGOC_CLUSTER_STATE_BORN: return _mongoc_cluster_sendv(&client->cluster, rpcs, rpcs_len, hint, write_concern, read_prefs, error); case MONGOC_CLUSTER_STATE_HEALTHY: case MONGOC_CLUSTER_STATE_UNHEALTHY: return _mongoc_cluster_try_sendv(&client->cluster, rpcs, rpcs_len, hint, write_concern, read_prefs, error); case MONGOC_CLUSTER_STATE_DEAD: bson_set_error(error, MONGOC_ERROR_CLIENT, MONGOC_ERROR_CLIENT_NOT_READY, "No healthy connections."); return false; default: BSON_ASSERT(false); return 0; } }
static bool _mongoc_sasl_start (mongoc_sasl_t *sasl, uint8_t *outbuf, uint32_t outbufmax, uint32_t *outbuflen, bson_error_t *error) { const char *service_name = "mongodb"; const char *service_host = ""; const char *mechanism = NULL; const char *raw = NULL; unsigned raw_len = 0; int status; BSON_ASSERT (sasl); BSON_ASSERT (outbuf); BSON_ASSERT (outbufmax); BSON_ASSERT (outbuflen); if (sasl->service_name) { service_name = sasl->service_name; } if (sasl->service_host) { service_host = sasl->service_host; } status = sasl_client_new (service_name, service_host, NULL, NULL, sasl->callbacks, 0, &sasl->conn); if (_mongoc_sasl_is_failure (status, error)) { return false; } status = sasl_client_start (sasl->conn, sasl->mechanism, &sasl->interact, &raw, &raw_len, &mechanism); if (_mongoc_sasl_is_failure (status, error)) { return false; } if ((0 != strcasecmp (mechanism, "GSSAPI")) && (0 != strcasecmp (mechanism, "PLAIN"))) { bson_set_error (error, MONGOC_ERROR_SASL, SASL_NOMECH, "SASL Failure: invalid mechanism \"%s\"", mechanism); return false; } status = sasl_encode64 (raw, raw_len, (char *)outbuf, outbufmax, outbuflen); if (_mongoc_sasl_is_failure (status, error)) { return false; } return true; }
static mongoc_matcher_op_t * _mongoc_matcher_parse (bson_iter_t *iter, /* IN */ bson_error_t *error) /* OUT */ { bson_iter_t child; const char *key; BSON_ASSERT (iter); key = bson_iter_key (iter); if (*key != '$') { return _mongoc_matcher_parse_compare (iter, key, error); } else { BSON_ASSERT (bson_iter_type(iter) == BSON_TYPE_ARRAY); if (!bson_iter_recurse (iter, &child)) { bson_set_error (error, MONGOC_ERROR_MATCHER, MONGOC_ERROR_MATCHER_INVALID, "Invalid value for operator \"%s\"", key); return NULL; } if (strcmp (key, "$or") == 0) { return _mongoc_matcher_parse_logical (MONGOC_MATCHER_OPCODE_OR, &child, false, error); } else if (strcmp(key, "$and") == 0) { return _mongoc_matcher_parse_logical (MONGOC_MATCHER_OPCODE_AND, &child, false, error); } else if (strcmp(key, "$nor") == 0) { return _mongoc_matcher_parse_logical (MONGOC_MATCHER_OPCODE_NOR, &child, false, error); } } bson_set_error (error, MONGOC_ERROR_MATCHER, MONGOC_ERROR_MATCHER_INVALID, "Invalid operator \"%s\"", key); return NULL; }
static bool txn_abort (mongoc_client_session_t *session, bson_t *reply, bson_error_t *error) { bson_t cmd = BSON_INITIALIZER; bson_t opts = BSON_INITIALIZER; bson_error_t err_local; bson_error_t *err_ptr = error ? error : &err_local; bson_t reply_local = BSON_INITIALIZER; mongoc_write_err_type_t error_type; bool r = false; _mongoc_bson_init_if_set (reply); if (!mongoc_client_session_append (session, &opts, err_ptr)) { GOTO (done); } if (session->txn.opts.write_concern) { if (!mongoc_write_concern_append (session->txn.opts.write_concern, &opts)) { bson_set_error (err_ptr, MONGOC_ERROR_TRANSACTION, MONGOC_ERROR_TRANSACTION_INVALID_STATE, "Invalid transaction write concern"); GOTO (done); } } BSON_APPEND_INT32 (&cmd, "abortTransaction", 1); /* will be reinitialized by mongoc_client_write_command_with_opts */ bson_destroy (&reply_local); r = mongoc_client_write_command_with_opts ( session->client, "admin", &cmd, &opts, &reply_local, err_ptr); /* Transactions Spec: "Drivers MUST retry the commitTransaction command once * after it fails with a retryable error", same for abort */ error_type = _mongoc_write_error_get_type (r, err_ptr, &reply_local); if (error_type == MONGOC_WRITE_ERR_RETRY) { bson_destroy (&reply_local); r = mongoc_client_write_command_with_opts ( session->client, "admin", &cmd, &opts, &reply_local, err_ptr); } if (!r) { /* we won't return an error from abortTransaction, so warn */ MONGOC_WARNING ("Error in abortTransaction: %s", err_ptr->message); } done: bson_destroy (&reply_local); bson_destroy (&cmd); bson_destroy (&opts); return r; }
static void test_bson_error_basic (void) { bson_error_t error; bson_set_error(&error, 123, 456, "%s %u", "localhost", 27017); assert(!strcmp(error.message, "localhost 27017")); assert_cmpint(error.domain, ==, 123); assert_cmpint(error.code, ==, 456); }
static bool _mongoc_server_session_uuid (uint8_t *data /* OUT */, bson_error_t *error) { #ifdef MONGOC_ENABLE_CRYPTO /* https://tools.ietf.org/html/rfc4122#page-14 * o Set the two most significant bits (bits 6 and 7) of the * clock_seq_hi_and_reserved to zero and one, respectively. * * o Set the four most significant bits (bits 12 through 15) of the * time_hi_and_version field to the 4-bit version number from * Section 4.1.3. * * o Set all the other bits to randomly (or pseudo-randomly) chosen * values. */ if (!_mongoc_rand_bytes (data, 16)) { bson_set_error (error, MONGOC_ERROR_CLIENT, MONGOC_ERROR_CLIENT_SESSION_FAILURE, "Could not generate UUID for logical session id"); return false; } data[6] = (uint8_t) (0x40 | (data[6] & 0xf)); data[8] = (uint8_t) (0x80 | (data[8] & 0x3f)); return true; #else /* no _mongoc_rand_bytes without a crypto library */ bson_set_error (error, MONGOC_ERROR_CLIENT, MONGOC_ERROR_CLIENT_SESSION_FAILURE, "Could not generate UUID for logical session id, we need a" " cryptography library like libcrypto, Common Crypto, or" " CNG"); return false; #endif }
bool _mongoc_read_prefs_validate (const mongoc_read_prefs_t *read_prefs, bson_error_t *error) { if (read_prefs && !mongoc_read_prefs_is_valid (read_prefs)) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "Invalid mongoc_read_prefs_t"); return false; } return true; }
bool _mongoc_write_concern_validate (const mongoc_write_concern_t *write_concern, bson_error_t *error) { if (write_concern && !mongoc_write_concern_is_valid (write_concern)) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "Invalid mongoc_write_concern_t"); return false; } return true; }
static void _bson_to_error (const bson_t *b, bson_error_t *error) { bson_iter_t iter; int code = 0; BSON_ASSERT(b); if (!error) { return; } if (bson_iter_init_find(&iter, b, "code") && BSON_ITER_HOLDS_INT32(&iter)) { code = bson_iter_int32(&iter); } if (bson_iter_init_find(&iter, b, "$err") && BSON_ITER_HOLDS_UTF8(&iter)) { bson_set_error(error, MONGOC_ERROR_QUERY, code, "%s", bson_iter_utf8(&iter, NULL)); return; } if (bson_iter_init_find(&iter, b, "errmsg") && BSON_ITER_HOLDS_UTF8(&iter)) { bson_set_error(error, MONGOC_ERROR_QUERY, code, "%s", bson_iter_utf8(&iter, NULL)); return; } bson_set_error(error, MONGOC_ERROR_QUERY, MONGOC_ERROR_QUERY_FAILURE, "An unknown error ocurred on the server."); }
static bool _mongoc_sasl_is_failure (int status, bson_error_t *error) { bool ret = (status < 0); if (ret) { switch (status) { case SASL_NOMEM: bson_set_error (error, MONGOC_ERROR_SASL, status, "SASL Failrue: insufficient memory."); break; case SASL_NOMECH: bson_set_error (error, MONGOC_ERROR_SASL, status, "SASL Failure: failure to negotiate mechanism"); break; case SASL_BADPARAM: bson_set_error (error, MONGOC_ERROR_SASL, status, "Bad parameter supplied. Please file a bug " "with mongo-c-driver."); break; default: bson_set_error (error, MONGOC_ERROR_SASL, status, "SASL Failure: (%d): %s", status, sasl_errstring (status, NULL, NULL)); break; } } return ret; }
void _empty_error (mongoc_write_command_t *command, bson_error_t *error) { static const uint32_t codes[] = {MONGOC_ERROR_COLLECTION_DELETE_FAILED, MONGOC_ERROR_COLLECTION_INSERT_FAILED, MONGOC_ERROR_COLLECTION_UPDATE_FAILED}; bson_set_error (error, MONGOC_ERROR_COLLECTION, codes[command->type], "Cannot do an empty %s", gCommandNames[command->type]); }
/** * mongoc_buffer_append_from_stream: * @buffer; A mongoc_buffer_t. * @stream: The stream to read from. * @size: The number of bytes to read. * @timeout_msec: The number of milliseconds to wait or -1 for the default * @error: A location for a bson_error_t, or NULL. * * Reads from stream @size bytes and stores them in @buffer. This can be used * in conjunction with reading RPCs from a stream. You read from the stream * into this buffer and then scatter the buffer into the RPC. * * Returns: true if successful; otherwise false and @error is set. */ bool _mongoc_buffer_append_from_stream (mongoc_buffer_t *buffer, mongoc_stream_t *stream, size_t size, int32_t timeout_msec, bson_error_t *error) { uint8_t *buf; ssize_t ret; ENTRY; BSON_ASSERT (buffer); BSON_ASSERT (stream); BSON_ASSERT (size); BSON_ASSERT (buffer->datalen); BSON_ASSERT ((buffer->datalen + size) < INT_MAX); if (!SPACE_FOR (buffer, size)) { if (buffer->len) { memmove (&buffer->data[0], &buffer->data[buffer->off], buffer->len); } buffer->off = 0; if (!SPACE_FOR (buffer, size)) { buffer->datalen = bson_next_power_of_two (size + buffer->len + buffer->off); buffer->data = (uint8_t *) buffer->realloc_func ( buffer->data, buffer->datalen, NULL); } } buf = &buffer->data[buffer->off + buffer->len]; BSON_ASSERT ((buffer->off + buffer->len + size) <= buffer->datalen); ret = mongoc_stream_read (stream, buf, size, size, timeout_msec); if (ret != size) { bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "Failed to read %" PRIu64 " bytes: socket error or timeout", (uint64_t) size); RETURN (false); } buffer->len += ret; RETURN (true); }
void _mongoc_write_command_execute (mongoc_write_command_t *command, /* IN */ mongoc_client_t *client, /* IN */ mongoc_server_stream_t *server_stream, /* IN */ const char *database, /* IN */ const char *collection, /* IN */ const mongoc_write_concern_t *write_concern, /* IN */ uint32_t offset, /* IN */ mongoc_write_result_t *result) /* OUT */ { ENTRY; BSON_ASSERT (command); BSON_ASSERT (client); BSON_ASSERT (server_stream); BSON_ASSERT (database); BSON_ASSERT (collection); BSON_ASSERT (result); if (!write_concern) { write_concern = client->write_concern; } if (!_mongoc_write_concern_is_valid(write_concern)) { bson_set_error (&result->error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "The write concern is invalid."); result->failed = true; EXIT; } if (!command->hint) { command->hint = server_stream->sd->id; } else { BSON_ASSERT (command->hint == server_stream->sd->id); } if (server_stream->sd->max_wire_version >= WIRE_VERSION_WRITE_CMD) { _mongoc_write_command (command, client, server_stream, database, collection, write_concern, offset, result, &result->error); } else { gLegacyWriteOps[command->type] (command, client, server_stream, database, collection, write_concern, offset, result, &result->error); } EXIT; }
static void missing_chunk (mongoc_gridfs_file_t *file) { bson_set_error (&file->error, MONGOC_ERROR_GRIDFS, MONGOC_ERROR_GRIDFS_CHUNK_MISSING, "missing chunk number %" PRId32, file->n); if (file->cursor) { mongoc_cursor_destroy (file->cursor); file->cursor = NULL; } }