int openssl_error(neo4j_logger_t *logger, uint_fast8_t level, const char *file, unsigned int line) { unsigned long code = ERR_get_error(); if (code == 0) { neo4j_log_error(logger, "OpenSSL error not available (%s:%d)", file, line); return NEO4J_UNEXPECTED_ERROR; } if (ERR_get_error() != 0) { neo4j_log_error(logger, "OpenSSL error stack too deep (%s:%d)", file, line); return NEO4J_UNEXPECTED_ERROR; } char ebuf[256]; ERR_error_string_n(code, ebuf, sizeof(ebuf)); neo4j_log(logger, level, "OpenSSL error: %lu:%s:%s:%s", code, ERR_lib_error_string(code), ERR_func_error_string(code), ERR_reason_error_string(code)); return NEO4J_UNEXPECTED_ERROR; }
int sha512_digest(unsigned char *buf, unsigned int *np, const void *s, size_t n, neo4j_logger_t *logger) { const EVP_MD *md = EVP_get_digestbyname("SHA512"); assert(md != NULL); if (md == NULL) { neo4j_log_error(logger, "OpenSSL failed to load digest SHA512"); errno = NEO4J_UNEXPECTED_ERROR; return -1; } EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); assert(mdctx != NULL); if (mdctx == NULL) { neo4j_log_error(logger, "OpenSSL `EVP_MD_CTX_create` failed"); errno = NEO4J_UNEXPECTED_ERROR; return -1; } if (EVP_DigestInit_ex(mdctx, md, NULL) != 1) { neo4j_log_error(logger, "OpenSSL `EVP_DigestInit_ex` failed"); errno = NEO4J_UNEXPECTED_ERROR; goto failure; } if (EVP_DigestUpdate(mdctx, s, n) != 1) { neo4j_log_error(logger, "OpenSSL `EVP_DigestUpdate` failed"); errno = NEO4J_UNEXPECTED_ERROR; goto failure; } if (EVP_DigestFinal_ex(mdctx, buf, np) != 1) { neo4j_log_error(logger, "OpenSSL `EVP_DigestFinal` failed"); errno = NEO4J_UNEXPECTED_ERROR; goto failure; } EVP_MD_CTX_destroy(mdctx); return 0; int errsv; failure: errsv = errno; EVP_MD_CTX_destroy(mdctx); errno = errsv; return -1; }
int neo4j_connect_tcp_socket(const char *hostname, const char *servname, const neo4j_config_t *config, neo4j_logger_t *logger) { REQUIRE(hostname != NULL, -1); struct addrinfo hints; struct addrinfo *candidate_addresses = NULL; int err = 0; init_getaddrinfo_hints(&hints); err = getaddrinfo(hostname, servname, &hints, &candidate_addresses); if (err) { errno = NEO4J_UNKNOWN_HOST; return -1; } int fd = -1; struct addrinfo *addr; for (addr = candidate_addresses; addr != NULL; addr = addr->ai_next) { fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if (fd < 0) { if (!unsupported_sock_error(errno)) continue; neo4j_log_error_errno(logger, "socket"); freeaddrinfo(candidate_addresses); return -1; } set_socket_options(fd, config, logger); char hostnum[NI_MAXHOST]; char servnum[NI_MAXSERV]; err = getnameinfo(addr->ai_addr, addr->ai_addrlen, hostnum, sizeof(hostnum), servnum, sizeof(servnum), NI_NUMERICHOST | NI_NUMERICSERV); if (err) { neo4j_log_error(logger, "getnameinfo: %s", gai_strerror(err)); freeaddrinfo(candidate_addresses); errno = NEO4J_UNEXPECTED_ERROR; return -1; } neo4j_log_debug(logger, "attempting connection to %s [%s]", hostnum, servnum); err = connect_with_timeout(fd, addr->ai_addr, addr->ai_addrlen, config->connect_timeout, logger); if (err == 0) { break; } else if (err < 0) { return -1; } char ebuf[256]; neo4j_log_info(logger, "connection to %s [%s] failed: %s", hostnum, servnum, neo4j_strerror(errno, ebuf, sizeof(ebuf))); close(fd); fd = -1; } freeaddrinfo(candidate_addresses); return fd; }
int append_result(run_result_stream_t *results, const neo4j_value_t *argv, uint16_t argc) { assert(results != NULL); neo4j_session_t *session = results->session; if (argc != 1) { neo4j_log_error(results->logger, "invalid number of fields in RECORD message received in %p", (void *)session); errno = EPROTO; return -1; } assert(argv != NULL); neo4j_type_t arg_type = neo4j_type(argv[0]); if (arg_type != NEO4J_LIST) { neo4j_log_error(results->logger, "invalid field in RECORD message received in %p" " (got %s, expected List)", (void *)session, neo4j_typestr(arg_type)); errno = EPROTO; return -1; } if (!results->streaming) { // discard memory for the record neo4j_mpool_drain(&(results->record_mpool)); return 0; } assert(session != NULL); neo4j_config_t *config = neo4j_session_config(session); result_record_t *record = neo4j_mpool_calloc(&(results->record_mpool), 1, sizeof(result_record_t)); if (record == NULL) { return -1; } record->refcount = 1; // save memory for the record with the record record->mpool = results->record_mpool; results->record_mpool = neo4j_std_mpool(config); record->list = argv[0]; record->next = NULL; neo4j_result_t *result = &(record->_result); result->field = run_result_field; result->retain = run_result_retain; result->release = run_result_release; if (results->records == NULL) { assert(results->records_tail == NULL); results->records = record; results->records_tail = record; } else { results->records_tail->next = record; results->records_tail = record; } if (results->awaiting_records > 0) { --(results->awaiting_records); } return 0; }
int stream_end(run_result_stream_t *results, neo4j_message_type_t type, const char *src_message_type, const neo4j_value_t *argv, uint16_t argc) { neo4j_logger_t *logger = results->logger; neo4j_session_t *session = results->session; if (session == NULL) { return 0; } neo4j_config_t *config = neo4j_session_config(session); if (type == NEO4J_IGNORED_MESSAGE) { if (results->failure == 0) { neo4j_log_error(logger, "unexpected IGNORED message received in %p" " (in response to %s, yet no failure occurred)", (void *)session, src_message_type); set_failure(results, errno = EPROTO); return -1; } return 0; } assert(results->failure == 0); if (type == NEO4J_FAILURE_MESSAGE) { return set_eval_failure(results, src_message_type, argv, argc); } if (type != NEO4J_SUCCESS_MESSAGE) { neo4j_log_error(logger, "unexpected %s message received in %p" " (in response to %s)", neo4j_message_type_str(type), (void *)session, src_message_type); set_failure(results, errno = EPROTO); return -1; } char description[128]; snprintf(description, sizeof(description), "SUCCESS in %p (response to %s)", (void *)session, src_message_type); const neo4j_value_t *metadata = neo4j_validate_metadata(argv, argc, description, logger); if (metadata == NULL) { set_failure(results, errno); return -1; } if (neo4j_log_is_enabled(logger, NEO4J_LOG_TRACE)) { neo4j_metadata_log(logger, NEO4J_LOG_TRACE, description, *metadata); } results->statement_type = neo4j_meta_statement_type(*metadata, description, logger); if (results->statement_type < 0) { set_failure(results, errno); return -1; } results->statement_plan = neo4j_meta_plan(*metadata, description, config, logger); if (results->statement_plan == NULL && errno != NEO4J_NO_PLAN_AVAILABLE) { set_failure(results, errno); return -1; } if (neo4j_meta_update_counts(&(results->update_counts), *metadata, description, logger)) { set_failure(results, errno); return -1; } return 0; }
int run_callback(void *cdata, neo4j_message_type_t type, const neo4j_value_t *argv, uint16_t argc) { assert(cdata != NULL); assert(argc == 0 || argv != NULL); run_result_stream_t *results = (run_result_stream_t *)cdata; neo4j_logger_t *logger = results->logger; neo4j_session_t *session = results->session; results->starting = false; --(results->refcount); if (session == NULL) { return 0; } if (type == NEO4J_FAILURE_MESSAGE) { return set_eval_failure(results, "RUN", argv, argc); } if (type == NEO4J_IGNORED_MESSAGE) { if (results->failure == 0) { set_failure(results, NEO4J_STATEMENT_PREVIOUS_FAILURE); } return 0; } char description[128]; snprintf(description, sizeof(description), "%s in %p (response to RUN)", neo4j_message_type_str(type), (void *)session); if (type != NEO4J_SUCCESS_MESSAGE) { neo4j_log_error(logger, "unexpected %s", description); set_failure(results, errno = EPROTO); return -1; } const neo4j_value_t *metadata = neo4j_validate_metadata(argv, argc, description, logger); if (metadata == NULL) { set_failure(results, errno); return -1; } if (neo4j_log_is_enabled(session->logger, NEO4J_LOG_TRACE)) { neo4j_metadata_log(logger, NEO4J_LOG_TRACE, description, *metadata); } if (neo4j_meta_fieldnames(&(results->fields), &(results->nfields), *metadata, &(results->mpool), description, logger)) { set_failure(results, errno); return -1; } return 0; }