1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-11-03 04:17:17 -05:00

Feature: Added basic way to export Icecast's internally used IDs as a valuefile

This commit is contained in:
Philipp Schafft 2024-01-21 17:26:31 +00:00
parent e3487e4c22
commit 1b7db528f4
6 changed files with 296 additions and 42 deletions

View File

@ -41,6 +41,7 @@ noinst_HEADERS = \
reportxml_helper.h \
json.h \
xml2json.h \
valuefile.h \
string_renderer.h \
listensocket.h \
fastevent.h \
@ -96,6 +97,7 @@ icecast_SOURCES = \
reportxml_helper.c \
json.c \
xml2json.c \
valuefile.c \
string_renderer.c \
listensocket.c \
fastevent.c \

View File

@ -16,132 +16,134 @@
#include "logging.h"
#define CATMODULE "errors"
#define BASE_DEF(x) .id = (x), .symbol = # x
// cut -d' ' -f2 x | while read x; do printf " {.id = %-60s .http_status = xxx,\n .message = \"\"},\n" "$x",; done
static const icecast_error_t __errors[] = {
{.id = ICECAST_ERROR_ADMIN_DEST_NOT_RUNNING, .http_status = 400,
{BASE_DEF(ICECAST_ERROR_ADMIN_DEST_NOT_RUNNING), .http_status = 400,
.uuid = "52735a81-16fe-4d7e-9984-5aed8a941055",
.message = "Destination not running"},
{.id = ICECAST_ERROR_ADMIN_METADAT_BADCALL, .http_status = 400,
{BASE_DEF(ICECAST_ERROR_ADMIN_METADAT_BADCALL), .http_status = 400,
.uuid = "85d33e67-5c4e-4511-b4fa-3ca69ccd03de",
.message = "illegal metadata call"},
{.id = ICECAST_ERROR_ADMIN_METADAT_NO_SUCH_ACTION, .http_status = 501,
{BASE_DEF(ICECAST_ERROR_ADMIN_METADAT_NO_SUCH_ACTION), .http_status = 501,
.uuid = "14f4d814-98d9-468c-8a0b-ba5e74c9d771",
.message = "No such action"},
{.id = ICECAST_ERROR_ADMIN_MISSING_PARAMETER, .http_status = 400,
{BASE_DEF(ICECAST_ERROR_ADMIN_MISSING_PARAMETER), .http_status = 400,
.uuid = "cb11dc71-6149-454c-8d4e-47a3af26b03a",
.message = "Missing parameter"},
{.id = ICECAST_ERROR_ADMIN_missing_parameter, .http_status = 400,
{BASE_DEF(ICECAST_ERROR_ADMIN_missing_parameter), .http_status = 400,
.uuid = "8be9ef0a-2b32-450c-aec9-a414ca0c074c",
.message = "missing parameter"},
{.id = ICECAST_ERROR_ADMIN_MOUNT_NOT_ACCEPT_URL_UPDATES, .http_status = 422,
{BASE_DEF(ICECAST_ERROR_ADMIN_MOUNT_NOT_ACCEPT_URL_UPDATES), .http_status = 422,
.uuid = "3bed51bb-a10f-4af3-9965-4e67181de7d6",
.message = "mountpoint will not accept URL updates"},
{.id = ICECAST_ERROR_ADMIN_NO_SUCH_DESTINATION, .http_status = 404,
{BASE_DEF(ICECAST_ERROR_ADMIN_NO_SUCH_DESTINATION), .http_status = 404,
.uuid = "c5f1ee06-46a0-4697-9f01-6e9fc333d555",
.message = "No such destination"},
{.id = ICECAST_ERROR_ADMIN_ROLEMGN_ADD_NOSYS, .http_status = 501,
{BASE_DEF(ICECAST_ERROR_ADMIN_ROLEMGN_ADD_NOSYS), .http_status = 501,
.uuid = "7e1a8426-2ae1-4a6b-bfd9-59d8f8153021",
.message = "Adding users to role not supported by role"},
{.id = ICECAST_ERROR_ADMIN_ROLEMGN_DELETE_NOSYS, .http_status = 501,
{BASE_DEF(ICECAST_ERROR_ADMIN_ROLEMGN_DELETE_NOSYS), .http_status = 501,
.uuid = "367fbad1-389e-4292-bba8-c97984e616cc",
.message = "Deleting users from role not supported by role"},
{.id = ICECAST_ERROR_ADMIN_ROLEMGN_ROLE_NOT_FOUND, .http_status = 404,
{BASE_DEF(ICECAST_ERROR_ADMIN_ROLEMGN_ROLE_NOT_FOUND), .http_status = 404,
.uuid = "59fe9c81-8c34-49ff-800f-7ec42ea498be",
.message = "Role not found"},
{.id = ICECAST_ERROR_ADMIN_SOURCE_DOES_NOT_EXIST, .http_status = 404,
{BASE_DEF(ICECAST_ERROR_ADMIN_SOURCE_DOES_NOT_EXIST), .http_status = 404,
.uuid = "2f51a026-02e4-4fe4-bf9d-cc16557b3b65",
.message = "Source does not exist"},
{.id = ICECAST_ERROR_ADMIN_SOURCE_IS_NOT_AVAILABLE, .http_status = 400,
{BASE_DEF(ICECAST_ERROR_ADMIN_SOURCE_IS_NOT_AVAILABLE), .http_status = 400,
.uuid = "00b9d977-f41d-455f-820f-6d457dffb246",
.message = "Source is not available"},
{.id = ICECAST_ERROR_ADMIN_SUPPLIED_MOUNTPOINTS_ARE_IDENTICAL, .http_status = 400,
{BASE_DEF(ICECAST_ERROR_ADMIN_SUPPLIED_MOUNTPOINTS_ARE_IDENTICAL), .http_status = 400,
.uuid = "4be9a010-7a3f-44e4-b74d-3c6d9c4f7236",
.message = "supplied mountpoints are identical"},
{.id = ICECAST_ERROR_ADMIN_UNRECOGNISED_COMMAND, .http_status = 400,
{BASE_DEF(ICECAST_ERROR_ADMIN_UNRECOGNISED_COMMAND), .http_status = 400,
.uuid = "811bddac-5be5-4580-9cde-7b849e66dfe5",
.message = "unrecognised command"},
{.id = ICECAST_ERROR_AUTH_BUSY, .http_status = 503,
{BASE_DEF(ICECAST_ERROR_AUTH_BUSY), .http_status = 503,
.uuid = "26708754-8f98-4191-81d1-7fb7246200d6",
.message = "busy, please try again later"},
{.id = ICECAST_ERROR_CON_CONTENT_TYPE_NOSYS, .http_status = 415,
{BASE_DEF(ICECAST_ERROR_CON_CONTENT_TYPE_NOSYS), .http_status = 415,
.uuid = "f684ad3c-513b-4d87-9a66-424788bc6adb",
.message = "Content-type not supported"},
{.id = ICECAST_ERROR_CON_INTERNAL_FORMAT_ALLOC_ERROR, .http_status = 500,
{BASE_DEF(ICECAST_ERROR_CON_INTERNAL_FORMAT_ALLOC_ERROR), .http_status = 500,
.uuid = "47a4b11b-5d2a-46e2-8948-942e7b0af3e6",
.message = "internal format allocation problem"},
{.id = ICECAST_ERROR_CON_MISSING_PASS_PARAMETER, .http_status = 400 /* XXX */,
{BASE_DEF(ICECAST_ERROR_CON_MISSING_PASS_PARAMETER), .http_status = 400 /* XXX */,
.uuid = "b59c3a05-e2b1-4a14-8798-bbe1ae46603b",
.message = "missing pass parameter"},
{.id = ICECAST_ERROR_CON_MOUNT_IN_USE, .http_status = 409,
{BASE_DEF(ICECAST_ERROR_CON_MOUNT_IN_USE), .http_status = 409,
.uuid = "c5724467-5f85-48c7-b45a-915c3150c292",
.message = "Mountpoint in use"},
{.id = ICECAST_ERROR_CON_MOUNTPOINT_NOT_STARTING_WITH_SLASH, .http_status = 400,
{BASE_DEF(ICECAST_ERROR_CON_MOUNTPOINT_NOT_STARTING_WITH_SLASH), .http_status = 400,
.uuid = "1ae45ead-40fc-4de2-b56f-e54d3247f2ee",
.message = "source mountpoint not starting with /"},
{.id = ICECAST_ERROR_CON_NO_CONTENT_TYPE_GIVEN, .http_status = 400,
{BASE_DEF(ICECAST_ERROR_CON_NO_CONTENT_TYPE_GIVEN), .http_status = 400,
.uuid = "2cd86778-ac30-49e7-a108-26d627a7923b",
.message = "No Content-type given"},
{.id = ICECAST_ERROR_CON_PER_CRED_CLIENT_LIMIT, .http_status = 429,
{BASE_DEF(ICECAST_ERROR_CON_PER_CRED_CLIENT_LIMIT), .http_status = 429,
.uuid = "9c72c1ec-f638-4d33-a077-6acbbff25317",
.message = "Reached limit of concurrent connections on those credentials"},
{.id = ICECAST_ERROR_CON_SOURCE_CLIENT_LIMIT, .http_status = 503,
{BASE_DEF(ICECAST_ERROR_CON_SOURCE_CLIENT_LIMIT), .http_status = 503,
.uuid = "c770182d-c854-422a-a8e5-7142689234a3",
.message = "too many sources connected"},
{.id = ICECAST_ERROR_CON_UNIMPLEMENTED, .http_status = 501,
{BASE_DEF(ICECAST_ERROR_CON_UNIMPLEMENTED), .http_status = 501,
.uuid = "58ce6cb4-72b4-49da-8ad2-feaf775bc61e",
.message = "Unimplemented"},
{.id = ICECAST_ERROR_CON_UNKNOWN_REQUEST, .http_status = 405,
{BASE_DEF(ICECAST_ERROR_CON_UNKNOWN_REQUEST), .http_status = 405,
.uuid = "78f590cc-8812-40d5-a4ef-17344ab75b35",
.message = "unknown request"},
{.id = ICECAST_ERROR_CON_UPGRADE_ERROR, .http_status = 400 /* XXX */,
{BASE_DEF(ICECAST_ERROR_CON_UPGRADE_ERROR), .http_status = 400 /* XXX */,
.uuid = "ec16f654-f262-415f-ab91-95703ae33704",
.message = "Can not upgrade protocol"},
{.id = ICECAST_ERROR_CON_MOUNT_NO_FOR_DIRECT_ACCESS, .http_status = 400 /* XXX */,
{BASE_DEF(ICECAST_ERROR_CON_MOUNT_NO_FOR_DIRECT_ACCESS), .http_status = 400 /* XXX */,
.uuid = "652548c6-2a7d-4c73-a1c5-e53759032bd1",
.message = "Mountpoint is not available for direct access"},
{.id = ICECAST_ERROR_FSERV_FILE_NOT_FOUND, .http_status = 404,
{BASE_DEF(ICECAST_ERROR_FSERV_FILE_NOT_FOUND), .http_status = 404,
.uuid = "18c32b43-0d8e-469d-b434-10133cdd06ad",
.message = "The file you requested could not be found"},
{.id = ICECAST_ERROR_FSERV_FILE_NOT_READABLE, .http_status = 404 /* XXX */,
{BASE_DEF(ICECAST_ERROR_FSERV_FILE_NOT_READABLE), .http_status = 404 /* XXX */,
.uuid = "c883d55d-fb41-4f4c-8800-563f5542f51d",
.message = "File not readable"},
{.id = ICECAST_ERROR_FSERV_REQUEST_RANGE_NOT_SATISFIABLE, .http_status = 416,
{BASE_DEF(ICECAST_ERROR_FSERV_REQUEST_RANGE_NOT_SATISFIABLE), .http_status = 416,
.uuid = "5874cc51-770b-42b5-82d2-737b2b406b30",
.message = "Request Range Not Satisfiable"},
{.id = ICECAST_ERROR_GEN_BUFFER_REALLOC, .http_status = 500,
{BASE_DEF(ICECAST_ERROR_GEN_BUFFER_REALLOC), .http_status = 500,
.uuid = "cda8203e-f237-4090-8d43-544efdd6295c",
.message = "Buffer reallocation failed."},
{.id = ICECAST_ERROR_GEN_CLIENT_LIMIT, .http_status = 503,
{BASE_DEF(ICECAST_ERROR_GEN_CLIENT_LIMIT), .http_status = 503,
.uuid = "87fd3e61-6702-4473-b506-f616d27a142f",
.message = "Icecast connection limit reached"},
{.id = ICECAST_ERROR_GEN_CLIENT_NEEDS_TO_AUTHENTICATE, .http_status = 401,
{BASE_DEF(ICECAST_ERROR_GEN_CLIENT_NEEDS_TO_AUTHENTICATE), .http_status = 401,
.uuid = "25387198-0643-4577-9139-7c4f24f59d4a",
.message = "You need to authenticate"},
{.id = ICECAST_ERROR_GEN_HEADER_GEN_FAILED, .http_status = 500,
{BASE_DEF(ICECAST_ERROR_GEN_HEADER_GEN_FAILED), .http_status = 500,
.uuid = "a8b3c3fe-cb87-45fe-9a9d-ee4c2075d43a",
.message = "Header generation failed."},
{.id = ICECAST_ERROR_GEN_MEMORY_EXHAUSTED, .http_status = 503,
{BASE_DEF(ICECAST_ERROR_GEN_MEMORY_EXHAUSTED), .http_status = 503,
.uuid = "18411e73-713e-4910-b7e4-52a2e324b4e0",
.message = "memory exhausted"},
{.id = ICECAST_ERROR_GEN_SAFE_METHOD_ON_UNSAFE_CALL, .http_status = 405,
{BASE_DEF(ICECAST_ERROR_GEN_SAFE_METHOD_ON_UNSAFE_CALL), .http_status = 405,
.uuid = "6f4c95e3-b446-4814-b4b8-0cb585dbe4bd",
.message = "Safe HTTP method used on unsafe call"},
{.id = ICECAST_ERROR_SOURCE_MOUNT_UNAVAILABLE, .http_status = 404 /* XXX */,
{BASE_DEF(ICECAST_ERROR_SOURCE_MOUNT_UNAVAILABLE), .http_status = 404 /* XXX */,
.uuid = "88d06875-fcf2-4417-84af-05866c97745c",
.message = "Mount unavailable"},
{.id = ICECAST_ERROR_SOURCE_STREAM_PREPARATION_ERROR, .http_status = 500 /* XXX */,
{BASE_DEF(ICECAST_ERROR_SOURCE_STREAM_PREPARATION_ERROR), .http_status = 500 /* XXX */,
.uuid = "9e50d94d-f03d-4515-8216-577bf8e9f70d",
.message = "Stream preparation error"},
{.id = ICECAST_ERROR_SOURCE_MAX_LISTENERS, .http_status = 503,
{BASE_DEF(ICECAST_ERROR_SOURCE_MAX_LISTENERS), .http_status = 503,
.uuid = "df147168-baaa-4959-82a4-746a1232927d",
.message = "Maximum listeners reached for this source"},
{.id = ICECAST_ERROR_XSLT_PARSE, .http_status = 404 /* XXX */,
{BASE_DEF(ICECAST_ERROR_XSLT_PARSE), .http_status = 404 /* XXX */,
.uuid = "f86b5b28-c1f8-49f6-a4cd-a18e2a6a44fd",
.message = "Could not parse XSLT file"},
{.id = ICECAST_ERROR_XSLT_problem, .http_status = 500,
{BASE_DEF(ICECAST_ERROR_XSLT_problem), .http_status = 500,
.uuid = "d3c6e4b3-7d6e-4191-a81b-970273067ae3",
.message = "XSLT problem"},
{.id = ICECAST_ERROR_RECURSIVE_ERROR, .http_status = 500,
{BASE_DEF(ICECAST_ERROR_RECURSIVE_ERROR), .http_status = 500,
.uuid = "13489d5c-eae6-4bf3-889e-ec1fa9a9b9ac",
.message = "Recursive error"}
};
@ -170,3 +172,10 @@ const icecast_error_t * error_get_by_uuid(const char *uuid)
return NULL;
}
const icecast_error_t * error_get_by_index(size_t idx) {
if (idx < (sizeof(__errors)/sizeof(*__errors))) {
return &(__errors[idx]);
}
return NULL;
}

View File

@ -59,11 +59,13 @@ struct icecast_error_tag {
const int http_status;
const char *uuid;
const char *message;
const char *symbol;
};
typedef struct icecast_error_tag icecast_error_t;
const icecast_error_t * error_get_by_id(icecast_error_id_t id);
const icecast_error_t * error_get_by_uuid(const char *uuid);
const icecast_error_t * error_get_by_index(size_t idx);
#endif /* __ERRORS_H__ */

View File

@ -45,6 +45,7 @@
#include <sys/utsname.h>
#endif
#include "icecasttypes.h"
#include <igloo/error.h>
#include "common/thread/thread.h"
@ -93,6 +94,8 @@
#include "prng.h"
#include "geoip.h"
#include "navigation.h"
#include "valuefile.h"
#include "string_renderer.h"
#include <libxml/xmlmemory.h>
@ -261,6 +264,13 @@ static void show_version(bool full)
}
}
static void export_database(void)
{
string_renderer_t * db = valuefile_export_database();
fputs(string_renderer_to_string_zero_copy(db), stdout);
igloo_ro_unref(&db);
}
static bool _parse_config_opts(int argc, char **argv, char *filename, size_t size)
{
int i;
@ -302,6 +312,9 @@ static bool _parse_config_opts(int argc, char **argv, char *filename, size_t siz
} else if (strcmp(opt, "-V") == 0) {
show_version(true);
exit(0);
} else if (strcmp(opt, "--export-database") == 0) {
export_database();
exit(0);
} else if (strcmp(opt, "-c") == 0) {
if ((i + 1) < argc) {
strncpy(filename, argv[++i], size-1);

210
src/valuefile.c Normal file
View File

@ -0,0 +1,210 @@
/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2024 , Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <igloo/ro.h>
#include <igloo/error.h>
#include "valuefile.h"
#include "string_renderer.h"
#include "global.h"
#include "errors.h"
#include "logging.h"
#define CATMODULE "valuefile"
// universal:
#define WK_ASI "ddd60c5c-2934-404f-8f2d-fcb4da88b633"
#define WK_TAGNAME "bfae7574-3dae-425d-89b1-9c087c140c23"
#define WK_ENGLISH "c50134ca-0a32-5c5c-833c-2686043c0b3f"
#define WK_GB_TEXT "0678cfe2-1386-43db-86a9-6c491b2df64c"
#define WK_RELATES_TO "079ab791-784e-4bb9-ae2d-07e01710a60c"
#define WK_SEE_ALSO "a75f9010-9db3-4d78-bd78-0dd528d6b55d"
#define WK_DEFAULT_TYPE "87c4892f-ae39-476e-8ed0-d9ed321dafe9"
#define WK_UNSIGNED_INT "dea3782c-6bcb-4ce9-8a39-f8dab399d75d"
// Icecast:
#define WK_EQ_HTTP "06cfbaf9-01fe-4d82-8075-0389231c46b3"
#define WK_STATE_info "c2bb1328-87d6-49ad-b7df-0b381a2e606d"
#define WK_STATE_error "e0faf79c-bddf-42d7-a237-975aca861a0b"
#define WK_STATE_warning "107c0e91-1fd8-4bbc-a54c-899cbb3d9bc6"
static const char *states[] = {WK_STATE_info, WK_STATE_error, WK_STATE_warning};
static const struct {
const char *uuid;
const char *symbol;
const char *tagname;
const char *text;
const char *state;
const unsigned int http_status;
} extra[] = {
{.uuid = "be7fac90-54fb-4673-9e0d-d15d6a4963a2", .symbol = "AUTH_ALTER_REDIRECT_SEE_OTHER", .http_status = 303},
{.uuid = "4b08a03a-ecce-4981-badf-26b0bb6c9d9c", .symbol = "AUTH_ALTER_REDIRECT_TEMPORARY", .http_status = 307},
{.uuid = "36bf6815-95cb-4cc8-a7b0-6b4b0c82ac5d", .symbol = "AUTH_ALTER_REDIRECT_PERMANENT", .http_status = 308},
{.uuid = WK_EQ_HTTP, .tagname = "equivalent-http-status"},
{.uuid = WK_STATE_info, .tagname = "info"},
{.uuid = WK_STATE_error, .tagname = "error"},
{.uuid = WK_STATE_warning, .tagname = "warning"},
// grep __reportxml_add_maintenance.\*\" admin.c | sed 's/^.*__reportxml_add_maintenance([^,]*,[^,]*, *"\([^"]*\)", *"\([^"]*\)", *"\([^"]*\)", NULL);.*$/{.uuid = "\1", .state = WK_STATE_\2, .text = "\3"},/'
{.uuid = "a93a842a-9664-43a9-b707-7f358066fe2b", .state = WK_STATE_error, .text = "Global client, and source limit is bigger than suitable for current open file limit."},
{.uuid = "fdbacc56-1150-4c79-b53a-43cc79046f40", .state = WK_STATE_info, .text = "Core files are disabled."},
{.uuid = "688bdebc-c190-4b5d-8764-3a050c48387a", .state = WK_STATE_info, .text = "Core files are enabled."},
{.uuid = "c704804e-d3b9-4544-898b-d477078135de", .state = WK_STATE_warning, .text = "Developer logging is active. This mode is not for production."},
{.uuid = "f90219e1-bd07-4b54-b1ee-0ba6a0289a15", .state = WK_STATE_error, .text = "IPv6 not enabled."},
{.uuid = "709ab43b-251d-49a5-a4fe-c749eaabf17c", .state = WK_STATE_info, .text = "IPv4-mapped IPv6 is available on this system."},
{.uuid = "c4f25c51-2720-4b38-a806-19ef024b5289", .state = WK_STATE_warning, .text = "Hostname is not set to anything useful in <hostname>."},
{.uuid = "8defae31-a52e-4bba-b904-76db5362860f", .state = WK_STATE_warning, .text = "No useful location is given in <location>."},
{.uuid = "cf86d88e-dc20-4359-b446-110e7065d17a", .state = WK_STATE_warning, .text = "No admin contact given in <admin>. YP directory support is disabled."},
{.uuid = "e2ba5a8b-4e4f-41ca-b455-68ae5fb6cae0", .state = WK_STATE_error, .text = "No PRNG seed configured. PRNG is insecure."},
{.uuid = "6620ef7b-46ef-4781-9a5e-8ee7f0f9d44e", .state = WK_STATE_error, .text = "Unknown tags are used in the config file. See the error.log for details."},
{.uuid = "b6224fc4-53a1-433f-a6cd-d5b85c60f1c9", .state = WK_STATE_error, .text = "Obsolete tags are used in the config file. See the error.log for details and update your configuration accordingly."},
{.uuid = "0f6f757d-52d8-4b9a-8e57-9bcd528fffba", .state = WK_STATE_error, .text = "Invalid tags are used in the config file. See the error.log for details and update your configuration accordingly."},
{.uuid = "8fc33086-274d-4ccb-b32f-599b3fa0f41a", .state = WK_STATE_error, .text = "The configuration did not validate. See the error.log for details and update your configuration accordingly."},
{.uuid = "6830cbf7-cd68-4c0c-ab5a-81499c70fd34", .state = WK_STATE_info, .text = "chroot configured and active."},
{.uuid = "2d584a76-e67c-4268-b7e8-139b0b9b1131", .state = WK_STATE_error, .text = "chroot configured but failed."},
{.uuid = "1a3fea5c-3352-4cb5-85cc-51ab9bd6ea83", .state = WK_STATE_error, .text = "chroot configured but not supported by operating system."},
{.uuid = "bab05e81-fd03-4773-9fc5-c4609883a5e3", .state = WK_STATE_info, .text = "Change of UID/GID configured and active."},
{.uuid = "4f856dd4-7aac-44b4-95b5-b6798f547603", .state = WK_STATE_error, .text = "Change of UID/GID configured but failed."},
{.uuid = "afcaa756-b91c-4496-a9e2-44400a18789c", .state = WK_STATE_error, .text = "Change of UID/GID configured but not supported by operating system."},
{.uuid = "f68dd8a3-22b1-4118-aba6-b039f2c5b51e", .state = WK_STATE_info, .text = "Currently no sources are connected to this server."},
{.uuid = "a3a51986-3bba-42b9-ad5c-d9ecc9967320", .state = WK_STATE_warning, .text = "Legacy sources are connected. See mount list for details."},
{.uuid = "08676614-50b4-4ea7-ba99-7c2ffcecf705", .state = WK_STATE_warning, .text = "More than 90% of the server's configured maximum clients are connected"},
{.uuid = "417ae59c-de19-4ed1-ade1-429c689f1152", .state = WK_STATE_info, .text = "More than 75% of the server's configured maximum clients are connected"},
{.uuid = "dc91ce96-f473-41d1-bfff-379666306911", .state = WK_STATE_info, .text = "Environment is noisy."},
{.uuid = "40d134e3-fbbe-46b1-a409-9b2ca8954528", .state = WK_STATE_warning, .text = "No secure password hash support detected."},
{NULL}
};
static igloo_error_t valuefile_value(string_renderer_t *renderer, const char *value, bool first)
{
if (!first)
string_renderer_add_string(renderer, " ");
if (!value) {
return string_renderer_add_string(renderer, "!null");
} else if (!*value) {
return string_renderer_add_string(renderer, "!empty");
}
return string_renderer_add_string_with_options(renderer, value, false, STRING_RENDERER_ENCODING_URI);
}
static igloo_error_t valuefile_line_metadata(string_renderer_t *renderer, const char *tag, const char *relation, const char *context, const char *type, const char *encoding, const char *value)
{
string_renderer_add_string(renderer, "tag-metadata ");
string_renderer_add_string(renderer, tag);
string_renderer_add_string(renderer, " ");
string_renderer_add_string(renderer, relation);
valuefile_value(renderer, context, false);
valuefile_value(renderer, type, false);
valuefile_value(renderer, encoding, false);
valuefile_value(renderer, value, false);
string_renderer_add_string(renderer, "\n");
return igloo_ERROR_NONE;
}
static igloo_error_t valuefile_line_relation(string_renderer_t *renderer, const char *tag, const char *relation, const char *related, const char *context, const char *filter)
{
string_renderer_add_string(renderer, "tag-relation ");
string_renderer_add_string(renderer, tag);
string_renderer_add_string(renderer, " ");
string_renderer_add_string(renderer, relation);
string_renderer_add_string(renderer, " ");
string_renderer_add_string(renderer, related);
valuefile_value(renderer, context, false);
valuefile_value(renderer, filter, false);
string_renderer_add_string(renderer, "\n");
return igloo_ERROR_NONE;
}
static igloo_error_t valuefile_line_tag_ise(string_renderer_t *renderer, const char *ise, const char *comment)
{
string_renderer_add_string(renderer, "tag-ise ");
string_renderer_add_string(renderer, ise);
if (comment) {
string_renderer_add_string(renderer, " # ");
string_renderer_add_string(renderer, comment);
}
string_renderer_add_string(renderer, "\n");
return igloo_ERROR_NONE;
}
static igloo_error_t valuefile_http_status(string_renderer_t *renderer, const char *tag, unsigned int http_status)
{
if (http_status < 100 || http_status > 599)
return igloo_ERROR_NONE;
string_renderer_add_string(renderer, "tag-metadata ");
string_renderer_add_string(renderer, tag);
string_renderer_add_string(renderer, " ");
string_renderer_add_string(renderer, WK_EQ_HTTP);
string_renderer_add_string(renderer, " !null !null !null ");
string_renderer_add_int(renderer, http_status);
string_renderer_add_string(renderer, "\n");
return igloo_ERROR_NONE;
}
string_renderer_t * valuefile_export_database(void)
{
string_renderer_t *renderer;
if (igloo_ro_new(&renderer, string_renderer_t, igloo_instance) != igloo_ERROR_NONE)
return NULL;
string_renderer_add_string(renderer, "!!ValueFile 54bf8af4-b1d7-44da-af48-5278d11e8f32 e5da6a39-46d5-48a9-b174-5c26008e208e\n");
string_renderer_add_string(renderer, "!!Feature f06c2226-b33e-48f2-9085-cd906a3dcee0 # tagpool-source-format-modern-limited\n");
string_renderer_add_string(renderer, "\n");
// errors:
string_renderer_add_string(renderer, "# Errors:\n");
for (size_t i = 0; ; i++) {
const icecast_error_t * error = error_get_by_index(i);
if (!error)
break;
valuefile_line_tag_ise(renderer, error->uuid, error->message);
valuefile_line_metadata(renderer, error->uuid, WK_ASI, NULL, WK_TAGNAME, NULL, error->symbol);
valuefile_line_metadata(renderer, error->uuid, WK_GB_TEXT, WK_ENGLISH, NULL, NULL, error->message);
valuefile_http_status(renderer, error->uuid, error->http_status);
}
string_renderer_add_string(renderer, "\n");
string_renderer_add_string(renderer, "# Extra:\n");
for (size_t i = 0; extra[i].uuid; i++) {
valuefile_line_tag_ise(renderer, extra[i].uuid, extra[i].symbol);
if (extra[i].symbol)
valuefile_line_metadata(renderer, extra[i].uuid, WK_ASI, NULL, WK_TAGNAME, NULL, extra[i].symbol);
if (extra[i].tagname)
valuefile_line_metadata(renderer, extra[i].uuid, WK_ASI, NULL, WK_TAGNAME, NULL, extra[i].tagname);
if (extra[i].text)
valuefile_line_metadata(renderer, extra[i].uuid, WK_GB_TEXT, WK_ENGLISH, NULL, NULL, extra[i].text);
if (extra[i].state)
valuefile_line_relation(renderer, extra[i].uuid, WK_RELATES_TO, extra[i].state, NULL, NULL);
valuefile_http_status(renderer, extra[i].uuid, extra[i].http_status);
}
string_renderer_add_string(renderer, "\n");
string_renderer_add_string(renderer, "# Special:\n");
valuefile_line_relation(renderer, WK_EQ_HTTP, WK_DEFAULT_TYPE, WK_UNSIGNED_INT, NULL, NULL);
for (size_t i = 0; i < (sizeof(states)/sizeof(*states)); i++) {
for (size_t j = 0; j < (sizeof(states)/sizeof(*states)); j++) {
if (i != j)
valuefile_line_relation(renderer, states[i], WK_SEE_ALSO, states[j], NULL, NULL);
}
}
string_renderer_add_string(renderer, "\n");
return renderer;
}

18
src/valuefile.h Normal file
View File

@ -0,0 +1,18 @@
/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2024 , Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
#ifndef __VALUEFILE_H__
#define __VALUEFILE_H__
#include <stdbool.h>
#include "icecasttypes.h"
string_renderer_t * valuefile_export_database(void);
#endif