/* This file is part of GNUnet Copyright (C) 2012-2022 GNUnet e.V. GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . SPDX-License-Identifier: AGPL3.0-or-later */ #include "gnunet_error_codes.h" #include #include #include /** * MHD does not define our value for 0 (client-side generated code). */ #define MHD_HTTP_UNINITIALIZED 0 /** * A pair containing an error code and its hint. */ struct ErrorCodeAndHint { /** * The error code. */ enum GNUNET_ErrorCode ec; /** * The hint. */ const char *hint; /** * The HTTP status code. */ unsigned int http_code; }; /** * The list of all error codes with their hints. */ static const struct ErrorCodeAndHint code_hint_pairs[] = { { .ec = GNUNET_EC_NONE, .hint = gettext_noop ("No error (success)."), .http_code = MHD_HTTP_UNINITIALIZED }, { .ec = GNUNET_EC_UNKNOWN, .hint = gettext_noop ("Unknown and unspecified error."), .http_code = MHD_HTTP_INTERNAL_SERVER_ERROR }, { .ec = GNUNET_EC_SERVICE_COMMUNICATION_FAILED, .hint = gettext_noop ("Communication with service failed."), .http_code = MHD_HTTP_INTERNAL_SERVER_ERROR }, { .ec = GNUNET_EC_IDENTITY_NOT_FOUND, .hint = gettext_noop ("Ego not found."), .http_code = MHD_HTTP_NOT_FOUND }, { .ec = GNUNET_EC_IDENTITY_NAME_CONFLICT, .hint = gettext_noop ("Identifier already in use for another ego."), .http_code = MHD_HTTP_CONFLICT }, { .ec = GNUNET_EC_IDENTITY_INVALID, .hint = gettext_noop ("The given ego is invalid or malformed."), .http_code = MHD_HTTP_INTERNAL_SERVER_ERROR }, { .ec = GNUNET_EC_NAMESTORE_UNKNOWN, .hint = gettext_noop ("Unknown namestore error."), .http_code = MHD_HTTP_INTERNAL_SERVER_ERROR }, { .ec = GNUNET_EC_NAMESTORE_ITERATION_FAILED, .hint = gettext_noop ("Zone iteration failed."), .http_code = MHD_HTTP_INTERNAL_SERVER_ERROR }, { .ec = GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND, .hint = gettext_noop ("Zone not found."), .http_code = MHD_HTTP_NOT_FOUND }, { .ec = GNUNET_EC_NAMESTORE_RECORD_NOT_FOUND, .hint = gettext_noop ("Record not found."), .http_code = MHD_HTTP_NOT_FOUND }, { .ec = GNUNET_EC_NAMESTORE_RECORD_DELETE_FAILED, .hint = gettext_noop ("Zone iteration failed."), .http_code = MHD_HTTP_INTERNAL_SERVER_ERROR }, { .ec = GNUNET_EC_NAMESTORE_ZONE_EMPTY, .hint = gettext_noop ("Zone does not contain any records."), .http_code = MHD_HTTP_NOT_FOUND }, { .ec = GNUNET_EC_NAMESTORE_LOOKUP_ERROR, .hint = gettext_noop ("Failed to lookup record."), .http_code = MHD_HTTP_INTERNAL_SERVER_ERROR }, { .ec = GNUNET_EC_NAMESTORE_NO_RECORDS_GIVEN, .hint = gettext_noop ("No records given."), .http_code = MHD_HTTP_BAD_REQUEST }, { .ec = GNUNET_EC_NAMESTORE_RECORD_DATA_INVALID, .hint = gettext_noop ("Record data invalid."), .http_code = MHD_HTTP_BAD_REQUEST }, { .ec = GNUNET_EC_NAMESTORE_NO_LABEL_GIVEN, .hint = gettext_noop ("No label given."), .http_code = MHD_HTTP_BAD_REQUEST }, { .ec = GNUNET_EC_NAMESTORE_NO_RESULTS, .hint = gettext_noop ("No results given."), .http_code = MHD_HTTP_NOT_FOUND }, { .ec = GNUNET_EC_NAMESTORE_RECORD_EXISTS, .hint = gettext_noop ("Record already exists."), .http_code = MHD_HTTP_CONFLICT }, { .ec = GNUNET_EC_NAMESTORE_RECORD_TOO_BIG, .hint = gettext_noop ("Record size exceeds maximum limit."), .http_code = MHD_HTTP_INTERNAL_SERVER_ERROR }, { .ec = GNUNET_EC_NAMESTORE_BACKEND_FAILED, .hint = gettext_noop ("There was an error in the database backend."), .http_code = MHD_HTTP_INTERNAL_SERVER_ERROR }, { .ec = GNUNET_EC_NAMESTORE_STORE_FAILED, .hint = gettext_noop ("Failed to store the given records."), .http_code = MHD_HTTP_INTERNAL_SERVER_ERROR }, { .ec = GNUNET_EC_NAMESTORE_LABEL_INVALID, .hint = gettext_noop ("Label invalid or malformed."), .http_code = MHD_HTTP_BAD_REQUEST }, }; /** * The length of @e code_hint_pairs. */ static const unsigned int code_hint_pairs_length = 22; const char * GNUNET_ErrorCode_get_hint (enum GNUNET_ErrorCode ec) { unsigned int lower = 0; unsigned int upper = code_hint_pairs_length - 1; unsigned int mid = upper / 2; while (lower <= upper) { mid = (upper + lower) / 2; if (code_hint_pairs[mid].ec < ec) { lower = mid + 1; } else if (code_hint_pairs[mid].ec > ec) { upper = mid - 1; } else { return code_hint_pairs[mid].hint; } } return ""; } unsigned int GNUNET_ErrorCode_get_http_status (enum GNUNET_ErrorCode ec) { unsigned int lower = 0; unsigned int upper = code_hint_pairs_length - 1; unsigned int mid = upper / 2; while (lower <= upper) { mid = (upper + lower) / 2; if (code_hint_pairs[mid].ec < ec) { lower = mid + 1; } else if (code_hint_pairs[mid].ec > ec) { upper = mid - 1; } else { return code_hint_pairs[mid].http_code; } } return UINT_MAX; } unsigned int GNUNET_ErrorCode_get_http_status_safe (enum GNUNET_ErrorCode ec) { unsigned int hc; hc = GNUNET_ErrorCode_get_http_status (ec); if ( (0 == hc) || (UINT_MAX == hc) ) return MHD_HTTP_INTERNAL_SERVER_ERROR; return hc; }