1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-12-04 14:46:30 -05:00

Feature: Generate errors based on IDs.

This generates error pages based on IDs. This allows to reuse errors
and add more advanced information to them.

This patch also makes Icecast send in plain text OR HTML based
on the clients Accept:-string.
This commit is contained in:
Philipp Schafft 2018-04-28 13:49:36 +00:00
parent b6cd41eab0
commit b42378abc4
14 changed files with 276 additions and 78 deletions

View File

@ -7,7 +7,7 @@ SUBDIRS = common/avl common/net common/thread common/httpp common/log common/tim
bin_PROGRAMS = icecast bin_PROGRAMS = icecast
noinst_HEADERS = admin.h cfgfile.h logging.h sighandler.h connection.h \ noinst_HEADERS = admin.h cfgfile.h logging.h sighandler.h connection.h \
global.h util.h curl.h slave.h source.h stats.h refbuf.h client.h playlist.h \ global.h util.h errors.h curl.h slave.h source.h stats.h refbuf.h client.h playlist.h \
compat.h fserve.h xslt.h yp.h md5.h matchfile.h tls.h \ compat.h fserve.h xslt.h yp.h md5.h matchfile.h tls.h \
event.h event_log.h event_exec.h event_url.h \ event.h event_log.h event_exec.h event_url.h \
acl.h auth.h \ acl.h auth.h \
@ -15,7 +15,7 @@ noinst_HEADERS = admin.h cfgfile.h logging.h sighandler.h connection.h \
format_vorbis.h format_theora.h format_flac.h format_speex.h format_midi.h \ format_vorbis.h format_theora.h format_flac.h format_speex.h format_midi.h \
format_kate.h format_skeleton.h format_opus.h format_kate.h format_skeleton.h format_opus.h
icecast_SOURCES = cfgfile.c main.c logging.c sighandler.c connection.c global.c \ icecast_SOURCES = cfgfile.c main.c logging.c sighandler.c connection.c global.c \
util.c slave.c source.c stats.c refbuf.c client.c playlist.c \ util.c errors.c slave.c source.c stats.c refbuf.c client.c playlist.c \
xslt.c fserve.c admin.c md5.c matchfile.c tls.c \ xslt.c fserve.c admin.c md5.c matchfile.c tls.c \
format.c format_ogg.c format_mp3.c format_midi.c format_flac.c format_ebml.c \ format.c format_ogg.c format_mp3.c format_midi.c format_flac.c format_ebml.c \
format_kate.c format_skeleton.c format_opus.c \ format_kate.c format_skeleton.c format_opus.c \

View File

@ -8,7 +8,7 @@
* oddsock <oddsock@xiph.org>, * oddsock <oddsock@xiph.org>,
* Karl Heyes <karl@xiph.org> * Karl Heyes <karl@xiph.org>
* and others (see AUTHORS for details). * and others (see AUTHORS for details).
* Copyright 2012-2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>, * Copyright 2012-2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -34,6 +34,7 @@
#include "xslt.h" #include "xslt.h"
#include "fserve.h" #include "fserve.h"
#include "admin.h" #include "admin.h"
#include "errors.h"
#include "format.h" #include "format.h"
@ -50,7 +51,7 @@
do { \ do { \
(var) = httpp_get_query_param((client)->parser, (name)); \ (var) = httpp_get_query_param((client)->parser, (name)); \
if((var) == NULL) { \ if((var) == NULL) { \
client_send_error((client), 400, 0, "Missing parameter"); \ client_send_error_by_id(client, ICECAST_ERROR_ADMIN_MISSING_PARAMETER); \
return; \ return; \
} \ } \
} while(0); } while(0);
@ -283,7 +284,7 @@ void admin_send_response(xmlDocPtr doc,
NULL, NULL, client); NULL, NULL, client);
if (ret < 0) { if (ret < 0) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error(client, 500, 0, "Header generation failed."); client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
xmlFree(buff); xmlFree(buff);
return; return;
} else if (buf_len < (size_t)(len + ret + 64)) { } else if (buf_len < (size_t)(len + ret + 64)) {
@ -300,13 +301,13 @@ void admin_send_response(xmlDocPtr doc,
NULL, NULL, client); NULL, NULL, client);
if (ret == -1) { if (ret == -1) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error(client, 500, 0, "Header generation failed."); client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
xmlFree(buff); xmlFree(buff);
return; return;
} }
} else { } else {
ICECAST_LOG_ERROR("Client buffer reallocation failed. Dropping client."); ICECAST_LOG_ERROR("Client buffer reallocation failed. Dropping client.");
client_send_error(client, 500, 0, "Buffer reallocation failed."); client_send_error_by_id(client, ICECAST_ERROR_GEN_BUFFER_REALLOC);
xmlFree(buff); xmlFree(buff);
return; return;
} }
@ -352,7 +353,7 @@ void admin_handle_request(client_t *client, const char *uri)
if (handler == NULL) { if (handler == NULL) {
ICECAST_LOG_ERROR("Error parsing command string or unrecognised command: %H", ICECAST_LOG_ERROR("Error parsing command string or unrecognised command: %H",
uri); uri);
client_send_error(client, 400, 0, "Unrecognised command"); client_send_error_by_id(client, ICECAST_ERROR_ADMIN_UNRECOGNISED_COMMAND);
return; return;
} }
@ -366,7 +367,7 @@ void admin_handle_request(client_t *client, const char *uri)
ICECAST_LOG_DEBUG("Granted right to call COMMAND_RAW_METADATA_UPDATE to " ICECAST_LOG_DEBUG("Granted right to call COMMAND_RAW_METADATA_UPDATE to "
"client because it is allowed to do SOURCE or PUT."); "client because it is allowed to do SOURCE or PUT.");
} else { } else {
client_send_error(client, 401, 1, "You need to authenticate\r\n"); client_send_error_by_id(client, ICECAST_ERROR_GEN_CLIENT_NEEDS_TO_AUTHENTICATE);
return; return;
} }
} }
@ -385,14 +386,14 @@ void admin_handle_request(client_t *client, const char *uri)
avl_tree_unlock(global.source_tree); avl_tree_unlock(global.source_tree);
ICECAST_LOG_WARN("Admin command \"%H\" on non-existent source \"%H\"", ICECAST_LOG_WARN("Admin command \"%H\" on non-existent source \"%H\"",
uri, mount); uri, mount);
client_send_error(client, 400, 0, "Source does not exist"); client_send_error_by_id(client, ICECAST_ERROR_ADMIN_SOURCE_DOES_NOT_EXIST);
return; return;
} /* No Source running */ } /* No Source running */
else if (source->running == 0 && source->on_demand == 0) { else if (source->running == 0 && source->on_demand == 0) {
avl_tree_unlock(global.source_tree); avl_tree_unlock(global.source_tree);
ICECAST_LOG_INFO("Received admin command \"%H\" on unavailable mount \"%H\"", ICECAST_LOG_INFO("Received admin command \"%H\" on unavailable mount \"%H\"",
uri, mount); uri, mount);
client_send_error(client, 400, 0, "Source is not available"); client_send_error_by_id(client, ICECAST_ERROR_ADMIN_SOURCE_IS_NOT_AVAILABLE);
return; return;
} }
ICECAST_LOG_INFO("Received admin command %H on mount '%s'", ICECAST_LOG_INFO("Received admin command %H on mount '%s'",
@ -400,7 +401,7 @@ void admin_handle_request(client_t *client, const char *uri)
} }
if (handler->type == ADMINTYPE_MOUNT && !source) { if (handler->type == ADMINTYPE_MOUNT && !source) {
client_send_error(client, 400, 0, "Mount parameter mandatory"); client_send_error_by_id(client, ICECAST_ERROR_ADMIN_MISSING_PARAMETER);
return; return;
} }
@ -422,7 +423,7 @@ static void html_success(client_t *client, char *message)
if (ret == -1 || ret >= PER_CLIENT_REFBUF_SIZE) { if (ret == -1 || ret >= PER_CLIENT_REFBUF_SIZE) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error(client, 500, 0, "Header generation failed."); client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
return; return;
} }
@ -463,17 +464,17 @@ static void command_move_clients(client_t *client,
dest = source_find_mount(dest_source); dest = source_find_mount(dest_source);
if (dest == NULL) { if (dest == NULL) {
client_send_error(client, 400, 0, "No such destination"); client_send_error_by_id(client, ICECAST_ERROR_ADMIN_NO_SUCH_DESTINATION);
return; return;
} }
if (strcmp(dest->mount, source->mount) == 0) { if (strcmp(dest->mount, source->mount) == 0) {
client_send_error(client, 400, 0, "supplied mountpoints are identical"); client_send_error_by_id(client, ICECAST_ERROR_ADMIN_SUPPLIED_MOUNTPOINTS_ARE_IDENTICAL);
return; return;
} }
if (dest->running == 0 && dest->on_demand == 0) { if (dest->running == 0 && dest->on_demand == 0) {
client_send_error(client, 400, 0, "Destination not running"); client_send_error_by_id(client, ICECAST_ERROR_ADMIN_DEST_NOT_RUNNING);
return; return;
} }
@ -611,7 +612,7 @@ static void command_buildm3u(client_t *client, source_t *source, int format)
if (ret == -1 || ret >= (PER_CLIENT_REFBUF_SIZE - 512)) { if (ret == -1 || ret >= (PER_CLIENT_REFBUF_SIZE - 512)) {
/* we want at least 512 Byte left for data */ /* we want at least 512 Byte left for data */
ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error(client, 500, 0, "Header generation failed."); client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
return; return;
} }
@ -664,8 +665,7 @@ static void command_manageauth(client_t *client, source_t *source, int response)
const char *idstring = NULL; const char *idstring = NULL;
char *message = NULL; char *message = NULL;
int ret = AUTH_OK; int ret = AUTH_OK;
int error_code = 400; int error_id = ICECAST_ERROR_ADMIN_missing_parameter;
const char *error_message = "missing parameter";
long unsigned int id; long unsigned int id;
ice_config_t *config = config_get_config(); ice_config_t *config = config_get_config();
auth_t *auth; auth_t *auth;
@ -692,8 +692,7 @@ static void command_manageauth(client_t *client, source_t *source, int response)
/* check if we found one */ /* check if we found one */
if (auth == NULL) { if (auth == NULL) {
ICECAST_LOG_WARN("Client requested mangement for unknown role %lu", id); ICECAST_LOG_WARN("Client requested mangement for unknown role %lu", id);
error_code = 404; error_id = ICECAST_ERROR_ADMIN_ROLEMGN_ROLE_NOT_FOUND;
error_message = "Role not found";
break; break;
} }
@ -713,7 +712,7 @@ static void command_manageauth(client_t *client, source_t *source, int response)
} }
if (!auth->adduser) { if (!auth->adduser) {
error_message = "Adding users to role not supported by role"; error_id = ICECAST_ERROR_ADMIN_ROLEMGN_ADD_NOSYS;
break; break;
} }
@ -733,7 +732,7 @@ static void command_manageauth(client_t *client, source_t *source, int response)
} }
if (!auth->deleteuser) { if (!auth->deleteuser) {
error_message = "Deleting users from role not supported by role"; error_id = ICECAST_ERROR_ADMIN_ROLEMGN_DELETE_NOSYS;
break; break;
} }
@ -774,7 +773,7 @@ static void command_manageauth(client_t *client, source_t *source, int response)
config_release_config(); config_release_config();
auth_release(auth); auth_release(auth);
client_send_error(client, error_code, 0, error_message); client_send_error_by_id(client, error_id);
} }
static void command_kill_source(client_t *client, static void command_kill_source(client_t *client,
@ -944,7 +943,7 @@ static void command_shoutcast_metadata(client_t *client,
if (source->shoutcast_compat == 0) { if (source->shoutcast_compat == 0) {
ICECAST_LOG_ERROR("illegal change of metadata on non-shoutcast " ICECAST_LOG_ERROR("illegal change of metadata on non-shoutcast "
"compatible stream"); "compatible stream");
client_send_error(client, 400, 0, "illegal metadata call"); client_send_error_by_id(client, ICECAST_ERROR_ADMIN_METADAT_BADCALL);
return; return;
} }
@ -957,7 +956,7 @@ static void command_shoutcast_metadata(client_t *client,
COMMAND_REQUIRE(client, "song", value); COMMAND_REQUIRE(client, "song", value);
if (strcmp (action, "updinfo") != 0) { if (strcmp (action, "updinfo") != 0) {
client_send_error(client, 400, 0, "No such action"); client_send_error_by_id(client, ICECAST_ERROR_ADMIN_METADAT_NO_SUCH_ACTION);
return; return;
} }
if (source->client && strcmp (client->con->ip, source->client->con->ip) != 0) if (source->client && strcmp (client->con->ip, source->client->con->ip) != 0)
@ -972,7 +971,7 @@ static void command_shoutcast_metadata(client_t *client,
source->mount, value); source->mount, value);
html_success(client, "Metadata update successful"); html_success(client, "Metadata update successful");
} else { } else {
client_send_error(client, 400, 0, "mountpoint will not accept URL updates"); client_send_error_by_id(client, ICECAST_ERROR_ADMIN_MOUNT_NOT_ACCEPT_URL_UPDATES);
} }
} }
@ -1022,7 +1021,7 @@ static void command_list_mounts(client_t *client, source_t *source, int response
if (ret == -1 || ret >= PER_CLIENT_REFBUF_SIZE) { if (ret == -1 || ret >= PER_CLIENT_REFBUF_SIZE) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error(client, 500, 0, "Header generation failed."); client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
return; return;
} }

View File

@ -8,7 +8,7 @@
* oddsock <oddsock@xiph.org>, * oddsock <oddsock@xiph.org>,
* Karl Heyes <karl@xiph.org> * Karl Heyes <karl@xiph.org>
* and others (see AUTHORS for details). * and others (see AUTHORS for details).
* Copyright 2013-2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>, * Copyright 2013-2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/ */
/** /**
@ -27,6 +27,7 @@
#include "auth.h" #include "auth.h"
#include "source.h" #include "source.h"
#include "client.h" #include "client.h"
#include "errors.h"
#include "cfgfile.h" #include "cfgfile.h"
#include "stats.h" #include "stats.h"
#include "common/httpp/httpp.h" #include "common/httpp/httpp.h"
@ -373,7 +374,7 @@ static void auth_add_client(auth_t *auth, client_t *client, void (*on_no_match)(
/* TODO: replace that magic number */ /* TODO: replace that magic number */
if (auth->pending_count > 100) { if (auth->pending_count > 100) {
ICECAST_LOG_WARN("too many clients awaiting authentication on auth %p", auth); ICECAST_LOG_WARN("too many clients awaiting authentication on auth %p", auth);
client_send_error(client, 403, 1, "busy, please try again later"); client_send_error_by_id(client, ICECAST_ERROR_AUTH_BUSY);
return; return;
} }

View File

@ -8,7 +8,7 @@
* oddsock <oddsock@xiph.org>, * oddsock <oddsock@xiph.org>,
* Karl Heyes <karl@xiph.org> * Karl Heyes <karl@xiph.org>
* and others (see AUTHORS for details). * and others (see AUTHORS for details).
* Copyright 2011-2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>, * Copyright 2011-2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/ */
/* client.c /* client.c
@ -34,6 +34,7 @@
#include "format.h" #include "format.h"
#include "stats.h" #include "stats.h"
#include "fserve.h" #include "fserve.h"
#include "errors.h"
#include "client.h" #include "client.h"
#include "auth.h" #include "auth.h"
@ -214,7 +215,7 @@ int client_read_bytes(client_t *client, void *buf, unsigned len)
return bytes; return bytes;
} }
void client_send_error(client_t *client, int status, int plain, const char *message) static inline void _client_send_error(client_t *client, int status, int plain, const char *message)
{ {
ssize_t ret; ssize_t ret;
refbuf_t *data; refbuf_t *data;
@ -264,6 +265,30 @@ void client_send_error(client_t *client, int status, int plain, const char *mess
fserve_add_client (client, NULL); fserve_add_client (client, NULL);
} }
void client_send_error_by_id(client_t *client, int id)
{
const icecast_error_t *error = error_get_by_id(id);
const char *pref;
int plain;
if (!error) {
client_send_500(client, "Unknown error ID");
return;
}
pref = util_http_select_best(httpp_getvar(client->parser, "accept"), "text/plain", "text/html", (const char*)NULL);
if (strcmp(pref, "text/plain") == 0) {
plain = 1;
} else if (strcmp(pref, "text/html") == 0) {
plain = 0;
} else {
plain = 1;
}
_client_send_error(client, error->http_status, plain, error->message);
}
void client_send_101(client_t *client, reuse_t reuse) void client_send_101(client_t *client, reuse_t reuse)
{ {
ssize_t ret; ssize_t ret;

View File

@ -8,7 +8,7 @@
* oddsock <oddsock@xiph.org>, * oddsock <oddsock@xiph.org>,
* Karl Heyes <karl@xiph.org> * Karl Heyes <karl@xiph.org>
* and others (see AUTHORS for details). * and others (see AUTHORS for details).
* Copyright 2011-2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>, * Copyright 2011-2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/ */
/* client.h /* client.h
@ -109,7 +109,7 @@ typedef struct _client_tag
int client_create (client_t **c_ptr, connection_t *con, http_parser_t *parser); int client_create (client_t **c_ptr, connection_t *con, http_parser_t *parser);
void client_destroy(client_t *client); void client_destroy(client_t *client);
void client_send_error(client_t *client, int status, int plain, const char *message); void client_send_error_by_id(client_t *client, int id);
void client_send_101(client_t *client, reuse_t reuse); void client_send_101(client_t *client, reuse_t reuse);
void client_send_426(client_t *client, reuse_t reuse); void client_send_426(client_t *client, reuse_t reuse);
int client_send_bytes (client_t *client, const void *buf, unsigned len); int client_send_bytes (client_t *client, const void *buf, unsigned len);

View File

@ -9,7 +9,7 @@
* Karl Heyes <karl@xiph.org> * Karl Heyes <karl@xiph.org>
* and others (see AUTHORS for details). * and others (see AUTHORS for details).
* Copyright 2011, Dave 'justdave' Miller <justdave@mozilla.com>, * Copyright 2011, Dave 'justdave' Miller <justdave@mozilla.com>,
* Copyright 2011-2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>, * Copyright 2011-2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/ */
/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- */
@ -46,6 +46,7 @@
#include "connection.h" #include "connection.h"
#include "refbuf.h" #include "refbuf.h"
#include "client.h" #include "client.h"
#include "errors.h"
#include "stats.h" #include "stats.h"
#include "logging.h" #include "logging.h"
#include "xslt.h" #include "xslt.h"
@ -575,7 +576,7 @@ void connection_queue(connection_t *con)
global_lock(); global_lock();
if (client_create(&client, con, NULL) < 0) { if (client_create(&client, con, NULL) < 0) {
global_unlock(); global_unlock();
client_send_error(client, 403, 1, "Icecast connection limit reached"); client_send_error_by_id(client, ICECAST_ERROR_GEN_CLIENT_LIMIT);
/* don't be too eager as this is an imposed hard limit */ /* don't be too eager as this is an imposed hard limit */
thread_sleep(400000); thread_sleep(400000);
return; return;
@ -659,7 +660,7 @@ int connection_complete_source(source_t *source, int response)
config_release_config(); config_release_config();
global_unlock(); global_unlock();
if (response) { if (response) {
client_send_error(source->client, 403, 1, "Content-type not supported"); client_send_error_by_id(source->client, ICECAST_ERROR_CON_CONTENT_TYPE_NOSYS);
source->client = NULL; source->client = NULL;
} }
ICECAST_LOG_WARN("Content-type \"%s\" not supported, dropping source", contenttype); ICECAST_LOG_WARN("Content-type \"%s\" not supported, dropping source", contenttype);
@ -669,7 +670,7 @@ int connection_complete_source(source_t *source, int response)
config_release_config(); config_release_config();
global_unlock(); global_unlock();
if (response) { if (response) {
client_send_error(source->client, 403, 1, "No Content-type given"); client_send_error_by_id(source->client, ICECAST_ERROR_CON_NO_CONTENT_TYPE_GIVEN);
source->client = NULL; source->client = NULL;
} }
ICECAST_LOG_ERROR("Content-type not given in PUT request, dropping source"); ICECAST_LOG_ERROR("Content-type not given in PUT request, dropping source");
@ -685,7 +686,7 @@ int connection_complete_source(source_t *source, int response)
global_unlock(); global_unlock();
config_release_config(); config_release_config();
if (response) { if (response) {
client_send_error(source->client, 403, 1, "internal format allocation problem"); client_send_error_by_id(source->client, ICECAST_ERROR_CON_INTERNAL_FORMAT_ALLOC_ERROR);
source->client = NULL; source->client = NULL;
} }
ICECAST_LOG_WARN("plugin format failed for \"%s\"", source->mount); ICECAST_LOG_WARN("plugin format failed for \"%s\"", source->mount);
@ -714,7 +715,7 @@ int connection_complete_source(source_t *source, int response)
config_release_config(); config_release_config();
if (response) { if (response) {
client_send_error(source->client, 403, 1, "too many sources connected"); client_send_error_by_id(source->client, ICECAST_ERROR_CON_SOURCE_CLIENT_LIMIT);
source->client = NULL; source->client = NULL;
} }
@ -754,7 +755,7 @@ static inline void source_startup(client_t *client, const char *uri)
if (transfer_encoding && strcasecmp(transfer_encoding, HTTPP_ENCODING_IDENTITY) != 0) { if (transfer_encoding && strcasecmp(transfer_encoding, HTTPP_ENCODING_IDENTITY) != 0) {
client->encoding = httpp_encoding_new(transfer_encoding); client->encoding = httpp_encoding_new(transfer_encoding);
if (!client->encoding) { if (!client->encoding) {
client_send_error(client, 501, 1, "Unimplemented"); client_send_error_by_id(client, ICECAST_ERROR_CON_UNIMPLEMENTED);
return; return;
} }
} }
@ -784,7 +785,7 @@ static inline void source_startup(client_t *client, const char *uri)
fserve_add_client_callback(client, source_client_callback, source); fserve_add_client_callback(client, source_client_callback, source);
} }
} else { } else {
client_send_error(client, 403, 1, "Mountpoint in use"); client_send_error_by_id(client, ICECAST_ERROR_CON_MOUNT_IN_USE);
ICECAST_LOG_WARN("Mountpoint %s in use", uri); ICECAST_LOG_WARN("Mountpoint %s in use", uri);
} }
} }
@ -797,7 +798,7 @@ static void _handle_source_request(client_t *client, const char *uri)
if (uri[0] != '/') { if (uri[0] != '/') {
ICECAST_LOG_WARN("source mountpoint not starting with /"); ICECAST_LOG_WARN("source mountpoint not starting with /");
client_send_error(client, 400, 1, "source mountpoint not starting with /"); client_send_error_by_id(client, ICECAST_ERROR_CON_MOUNTPOINT_NOT_STARTING_WITH_SLASH);
return; return;
} }
@ -932,7 +933,7 @@ static void _handle_get_request(client_t *client, char *uri) {
if (client->protocol == ICECAST_PROTOCOL_SHOUTCAST) { if (client->protocol == ICECAST_PROTOCOL_SHOUTCAST) {
client_destroy(client); client_destroy(client);
} else { } else {
client_send_error(client, 401, 1, "You need to authenticate\r\n"); client_send_error_by_id(client, ICECAST_ERROR_GEN_CLIENT_NEEDS_TO_AUTHENTICATE);
} }
return; return;
} }
@ -954,8 +955,7 @@ static void _handle_get_request(client_t *client, char *uri) {
/* check for duplicate_logins */ /* check for duplicate_logins */
if (max_connections_per_user > 0) { /* -1 = not set (-> default=unlimited), 0 = unlimited */ if (max_connections_per_user > 0) { /* -1 = not set (-> default=unlimited), 0 = unlimited */
if (max_connections_per_user <= __count_user_role_on_mount(source, client)) { if (max_connections_per_user <= __count_user_role_on_mount(source, client)) {
client_send_error(client, 403, 1, "Reached limit of concurrent " client_send_error_by_id(client, ICECAST_ERROR_CON_PER_CRED_CLIENT_LIMIT);
"connections on those credentials");
in_error = 1; in_error = 1;
} }
} }
@ -976,7 +976,7 @@ static void _handle_get_request(client_t *client, char *uri) {
client->con->discon_time = connection_duration + time(NULL); client->con->discon_time = connection_duration + time(NULL);
} }
if (!in_error && __add_listener_to_source(source, client) == -1) { if (!in_error && __add_listener_to_source(source, client) == -1) {
client_send_error(client, 403, 1, "Rejecting client for whatever reason"); client_send_error_by_id(client, ICECAST_ERROR_CON_rejecting_client_for_whatever_reason);
} }
avl_tree_unlock(global.source_tree); avl_tree_unlock(global.source_tree);
} else { } else {
@ -1143,14 +1143,14 @@ static void _handle_authed_client(client_t *client, void *uri, auth_result resul
client->authstack = NULL; client->authstack = NULL;
if (result != AUTH_OK) { if (result != AUTH_OK) {
client_send_error(client, 401, 1, "You need to authenticate\r\n"); client_send_error_by_id(client, ICECAST_ERROR_GEN_CLIENT_NEEDS_TO_AUTHENTICATE);
free(uri); free(uri);
return; return;
} }
if (acl_test_method(client->acl, client->parser->req_type) != ACL_POLICY_ALLOW) { if (acl_test_method(client->acl, client->parser->req_type) != ACL_POLICY_ALLOW) {
ICECAST_LOG_ERROR("Client (role=%s, username=%s) not allowed to use this request method on %H", client->role, client->username, uri); ICECAST_LOG_ERROR("Client (role=%s, username=%s) not allowed to use this request method on %H", client->role, client->username, uri);
client_send_error(client, 401, 1, "You need to authenticate\r\n"); client_send_error_by_id(client, ICECAST_ERROR_GEN_CLIENT_NEEDS_TO_AUTHENTICATE);
free(uri); free(uri);
return; return;
} }
@ -1168,7 +1168,7 @@ static void _handle_authed_client(client_t *client, void *uri, auth_result resul
break; break;
default: default:
ICECAST_LOG_ERROR("Wrong request type from client"); ICECAST_LOG_ERROR("Wrong request type from client");
client_send_error(client, 400, 0, "unknown request"); client_send_error_by_id(client, ICECAST_ERROR_CON_UNKNOWN_REQUEST);
break; break;
} }
@ -1357,7 +1357,7 @@ static void _handle_connection(void)
connection = httpp_getvar(parser, "connection"); connection = httpp_getvar(parser, "connection");
if (upgrade && connection && strcasecmp(connection, "upgrade") == 0) { if (upgrade && connection && strcasecmp(connection, "upgrade") == 0) {
if (client->con->tlsmode == ICECAST_TLSMODE_DISABLED || strstr(upgrade, "TLS/1.0") == NULL) { if (client->con->tlsmode == ICECAST_TLSMODE_DISABLED || strstr(upgrade, "TLS/1.0") == NULL) {
client_send_error(client, 400, 1, "Can not upgrade protocol"); client_send_error_by_id(client, ICECAST_ERROR_CON_UPGRADE_ERROR);
continue; continue;
} else { } else {
client_send_101(client, ICECAST_REUSE_UPGRADETLS); client_send_101(client, ICECAST_REUSE_UPGRADETLS);
@ -1386,7 +1386,7 @@ static void _handle_connection(void)
client->admin_command = admin_get_command(uri + 1); client->admin_command = admin_get_command(uri + 1);
__prepare_shoutcast_admin_cgi_request(client); __prepare_shoutcast_admin_cgi_request(client);
if (!client->password) { if (!client->password) {
client_send_error(client, 400, 0, "missing pass parameter"); client_send_error_by_id(client, ICECAST_ERROR_CON_MISSING_PASS_PARAMETER);
continue; continue;
} }
} else if (strncmp("/admin/", uri, 7) == 0) { } else if (strncmp("/admin/", uri, 7) == 0) {

110
src/errors.c Normal file
View File

@ -0,0 +1,110 @@
/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "errors.h"
#include "logging.h"
#define CATMODULE "errors"
// cut -d' ' -f2 x | while read x; do printf " {.id = %-60s .http_status = xxx,\n .message = \"\"},\n" "$x",; done
const icecast_error_t __errors[] = {
{.id = ICECAST_ERROR_ADMIN_DEST_NOT_RUNNING, .http_status = 400,
.message = "Destination not running"},
{.id = ICECAST_ERROR_ADMIN_METADAT_BADCALL, .http_status = 400,
.message = "illegal metadata call"},
{.id = ICECAST_ERROR_ADMIN_METADAT_NO_SUCH_ACTION, .http_status = 501,
.message = "No such action"},
{.id = ICECAST_ERROR_ADMIN_MISSING_PARAMETER, .http_status = 400,
.message = "Missing parameter"},
{.id = ICECAST_ERROR_ADMIN_missing_parameter, .http_status = 400,
.message = "missing parameter"},
{.id = ICECAST_ERROR_ADMIN_MOUNT_NOT_ACCEPT_URL_UPDATES, .http_status = 501,
.message = "mountpoint will not accept URL updates"},
{.id = ICECAST_ERROR_ADMIN_NO_SUCH_DESTINATION, .http_status = 404,
.message = "No such destination"},
{.id = ICECAST_ERROR_ADMIN_ROLEMGN_ADD_NOSYS, .http_status = 501,
.message = "Adding users to role not supported by role"},
{.id = ICECAST_ERROR_ADMIN_ROLEMGN_DELETE_NOSYS, .http_status = 501,
.message = "Deleting users from role not supported by role"},
{.id = ICECAST_ERROR_ADMIN_ROLEMGN_ROLE_NOT_FOUND, .http_status = 404,
.message = "Role not found"},
{.id = ICECAST_ERROR_ADMIN_SOURCE_DOES_NOT_EXIST, .http_status = 404,
.message = "Source does not exist"},
{.id = ICECAST_ERROR_ADMIN_SOURCE_IS_NOT_AVAILABLE, .http_status = 400,
.message = "Source is not available"},
{.id = ICECAST_ERROR_ADMIN_SUPPLIED_MOUNTPOINTS_ARE_IDENTICAL, .http_status = 400,
.message = "supplied mountpoints are identical"},
{.id = ICECAST_ERROR_ADMIN_UNRECOGNISED_COMMAND, .http_status = 400,
.message = "unrecognised command"},
{.id = ICECAST_ERROR_AUTH_BUSY, .http_status = 503,
.message = "busy, please try again later"},
{.id = ICECAST_ERROR_CON_CONTENT_TYPE_NOSYS, .http_status = 415,
.message = "Content-type not supported"},
{.id = ICECAST_ERROR_CON_INTERNAL_FORMAT_ALLOC_ERROR, .http_status = 500,
.message = "internal format allocation problem"},
{.id = ICECAST_ERROR_CON_MISSING_PASS_PARAMETER, .http_status = 400 /* XXX */,
.message = "missing pass parameter"},
{.id = ICECAST_ERROR_CON_MOUNT_IN_USE, .http_status = 409,
.message = "Mountpoint in use"},
{.id = ICECAST_ERROR_CON_MOUNTPOINT_NOT_STARTING_WITH_SLASH, .http_status = 400,
.message = "source mountpoint not starting with /"},
{.id = ICECAST_ERROR_CON_NO_CONTENT_TYPE_GIVEN, .http_status = 400,
.message = "No Content-type given"},
{.id = ICECAST_ERROR_CON_PER_CRED_CLIENT_LIMIT, .http_status = 429,
.message = "Reached limit of concurrent connections on those credentials"},
{.id = ICECAST_ERROR_CON_rejecting_client_for_whatever_reason, .http_status = 403 /* XXX */,
.message = "Rejecting client for whatever reason"},
{.id = ICECAST_ERROR_CON_SOURCE_CLIENT_LIMIT, .http_status = 503,
.message = "too many sources connected"},
{.id = ICECAST_ERROR_CON_UNIMPLEMENTED, .http_status = 501,
.message = "Unimplemented"},
{.id = ICECAST_ERROR_CON_UNKNOWN_REQUEST, .http_status = 405,
.message = "unknown request"},
{.id = ICECAST_ERROR_CON_UPGRADE_ERROR, .http_status = 400 /* XXX */,
.message = "Can not upgrade protocol"},
{.id = ICECAST_ERROR_FSERV_FILE_NOT_FOUND, .http_status = 404,
.message = "The file you requested could not be found"},
{.id = ICECAST_ERROR_FSERV_FILE_NOT_READABLE, .http_status = 404 /* XXX */,
.message = "File not readable"},
{.id = ICECAST_ERROR_FSERV_REQUEST_RANGE_NOT_SATISFIABLE, .http_status = 416,
.message = "Request Range Not Satisfiable"},
{.id = ICECAST_ERROR_GEN_BUFFER_REALLOC, .http_status = 500,
.message = "Buffer reallocation failed."},
{.id = ICECAST_ERROR_GEN_CLIENT_LIMIT, .http_status = 503,
.message = "Icecast connection limit reached"},
{.id = ICECAST_ERROR_GEN_CLIENT_NEEDS_TO_AUTHENTICATE, .http_status = 401,
.message = "You need to authenticate"},
{.id = ICECAST_ERROR_GEN_HEADER_GEN_FAILED, .http_status = 500,
.message = "Header generation failed."},
{.id = ICECAST_ERROR_GEN_MEMORY_EXHAUSTED, .http_status = 503,
.message = "memory exhausted"},
{.id = ICECAST_ERROR_SOURCE_MOUNT_UNAVAILABLE, .http_status = 404 /* XXX */,
.message = "Mount unavailable"},
{.id = ICECAST_ERROR_SOURCE_STREAM_PREPARATION_ERROR, .http_status = 500 /* XXX */,
.message = "Stream preparation error"},
{.id = ICECAST_ERROR_XSLT_PARSE, .http_status = 404 /* XXX */,
.message = "Could not parse XSLT file"},
{.id = ICECAST_ERROR_XSLT_problem, .http_status = 500,
.message = "XSLT problem"}
};
const icecast_error_t * error_get_by_id(int id) {
size_t i;
for (i = 0; i < (sizeof(__errors)/sizeof(*__errors)); i++) {
if (__errors[i].id == id) {
return &(__errors[i]);
}
}
return NULL;
}

62
src/errors.h Normal file
View File

@ -0,0 +1,62 @@
/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
*/
#ifndef __ERRORS_H__
#define __ERRORS_H__
#define ICECAST_ERROR_ADMIN_DEST_NOT_RUNNING 1
#define ICECAST_ERROR_ADMIN_METADAT_BADCALL 2
#define ICECAST_ERROR_ADMIN_METADAT_NO_SUCH_ACTION 3
#define ICECAST_ERROR_ADMIN_MISSING_PARAMETER 4
#define ICECAST_ERROR_ADMIN_missing_parameter 5 /* what is this? */
#define ICECAST_ERROR_ADMIN_MOUNT_NOT_ACCEPT_URL_UPDATES 6
#define ICECAST_ERROR_ADMIN_NO_SUCH_DESTINATION 7
#define ICECAST_ERROR_ADMIN_ROLEMGN_ADD_NOSYS 8
#define ICECAST_ERROR_ADMIN_ROLEMGN_DELETE_NOSYS 9
#define ICECAST_ERROR_ADMIN_ROLEMGN_ROLE_NOT_FOUND 10
#define ICECAST_ERROR_ADMIN_SOURCE_DOES_NOT_EXIST 11
#define ICECAST_ERROR_ADMIN_SOURCE_IS_NOT_AVAILABLE 12
#define ICECAST_ERROR_ADMIN_SUPPLIED_MOUNTPOINTS_ARE_IDENTICAL 13
#define ICECAST_ERROR_ADMIN_UNRECOGNISED_COMMAND 14
#define ICECAST_ERROR_AUTH_BUSY 15
#define ICECAST_ERROR_CON_CONTENT_TYPE_NOSYS 16
#define ICECAST_ERROR_CON_INTERNAL_FORMAT_ALLOC_ERROR 17
#define ICECAST_ERROR_CON_MISSING_PASS_PARAMETER 18
#define ICECAST_ERROR_CON_MOUNT_IN_USE 19
#define ICECAST_ERROR_CON_MOUNTPOINT_NOT_STARTING_WITH_SLASH 20
#define ICECAST_ERROR_CON_NO_CONTENT_TYPE_GIVEN 21
#define ICECAST_ERROR_CON_PER_CRED_CLIENT_LIMIT 22
#define ICECAST_ERROR_CON_rejecting_client_for_whatever_reason 23 /* ??? */
#define ICECAST_ERROR_CON_SOURCE_CLIENT_LIMIT 24
#define ICECAST_ERROR_CON_UNIMPLEMENTED 25
#define ICECAST_ERROR_CON_UNKNOWN_REQUEST 26
#define ICECAST_ERROR_CON_UPGRADE_ERROR 27
#define ICECAST_ERROR_FSERV_FILE_NOT_FOUND 28
#define ICECAST_ERROR_FSERV_FILE_NOT_READABLE 29
#define ICECAST_ERROR_FSERV_REQUEST_RANGE_NOT_SATISFIABLE 30
#define ICECAST_ERROR_GEN_BUFFER_REALLOC 31
#define ICECAST_ERROR_GEN_CLIENT_LIMIT 32
#define ICECAST_ERROR_GEN_CLIENT_NEEDS_TO_AUTHENTICATE 33
#define ICECAST_ERROR_GEN_HEADER_GEN_FAILED 34
#define ICECAST_ERROR_GEN_MEMORY_EXHAUSTED 35
#define ICECAST_ERROR_SOURCE_MOUNT_UNAVAILABLE 36
#define ICECAST_ERROR_SOURCE_STREAM_PREPARATION_ERROR 37
#define ICECAST_ERROR_XSLT_PARSE 38
#define ICECAST_ERROR_XSLT_problem 39
struct icecast_error_tag {
const int id;
const int http_status;
const char *message;
};
typedef struct icecast_error_tag icecast_error_t;
const icecast_error_t * error_get_by_id(int id);
#endif /* __ERRORS_H__ */

View File

@ -8,7 +8,7 @@
* oddsock <oddsock@xiph.org>, * oddsock <oddsock@xiph.org>,
* Karl Heyes <karl@xiph.org> * Karl Heyes <karl@xiph.org>
* and others (see AUTHORS for details). * and others (see AUTHORS for details).
* Copyright 2011, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>. * Copyright 2011-2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>.
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -51,6 +51,7 @@
#include "global.h" #include "global.h"
#include "refbuf.h" #include "refbuf.h"
#include "client.h" #include "client.h"
#include "errors.h"
#include "stats.h" #include "stats.h"
#include "format.h" #include "format.h"
#include "logging.h" #include "logging.h"
@ -440,7 +441,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
if (m3u_requested == 0 && xslt_playlist_requested == NULL) if (m3u_requested == 0 && xslt_playlist_requested == NULL)
{ {
ICECAST_LOG_WARN("req for file \"%H\" %s", fullpath, strerror (errno)); ICECAST_LOG_WARN("req for file \"%H\" %s", fullpath, strerror (errno));
client_send_error(httpclient, 404, 0, "The file you requested could not be found"); client_send_error_by_id(httpclient, ICECAST_ERROR_FSERV_FILE_NOT_FOUND);
free (fullpath); free (fullpath);
return -1; return -1;
} }
@ -469,7 +470,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
"audio/x-mpegurl", NULL, "", NULL, httpclient); "audio/x-mpegurl", NULL, "", NULL, httpclient);
if (ret == -1 || ret >= (BUFSIZE - 512)) { /* we want at least 512 bytes left for the content of the playlist */ if (ret == -1 || ret >= (BUFSIZE - 512)) { /* we want at least 512 bytes left for the content of the playlist */
ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error(httpclient, 500, 0, "Header generation failed."); client_send_error_by_id(httpclient, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
free(sourceuri); free(sourceuri);
return -1; return -1;
} }
@ -517,7 +518,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
if (config->fileserve == 0) if (config->fileserve == 0)
{ {
ICECAST_LOG_DEBUG("on demand file \"%H\" refused. Serving static files has been disabled in the config", fullpath); ICECAST_LOG_DEBUG("on demand file \"%H\" refused. Serving static files has been disabled in the config", fullpath);
client_send_error(httpclient, 404, 0, "The file you requested could not be found"); client_send_error_by_id(httpclient, ICECAST_ERROR_FSERV_FILE_NOT_FOUND);
config_release_config(); config_release_config();
free(fullpath); free(fullpath);
return -1; return -1;
@ -526,7 +527,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
if (S_ISREG (file_buf.st_mode) == 0) if (S_ISREG (file_buf.st_mode) == 0)
{ {
client_send_error(httpclient, 404, 0, "The file you requested could not be found"); client_send_error_by_id(httpclient, ICECAST_ERROR_FSERV_FILE_NOT_FOUND);
ICECAST_LOG_WARN("found requested file but there is no handler for it: %H", fullpath); ICECAST_LOG_WARN("found requested file but there is no handler for it: %H", fullpath);
free (fullpath); free (fullpath);
return -1; return -1;
@ -536,7 +537,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
if (file == NULL) if (file == NULL)
{ {
ICECAST_LOG_WARN("Problem accessing file \"%H\"", fullpath); ICECAST_LOG_WARN("Problem accessing file \"%H\"", fullpath);
client_send_error(httpclient, 404, 0, "File not readable"); client_send_error_by_id(httpclient, ICECAST_ERROR_FSERV_FILE_NOT_READABLE);
free (fullpath); free (fullpath);
return -1; return -1;
} }
@ -585,7 +586,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
NULL, NULL, httpclient); NULL, NULL, httpclient);
if (bytes == -1 || bytes >= (BUFSIZE - 512)) { /* we want at least 512 bytes left */ if (bytes == -1 || bytes >= (BUFSIZE - 512)) { /* we want at least 512 bytes left */
ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error(httpclient, 500, 0, "Header generation failed."); client_send_error_by_id(httpclient, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
return -1; return -1;
} }
bytes += snprintf (httpclient->refbuf->data + bytes, BUFSIZE - bytes, bytes += snprintf (httpclient->refbuf->data + bytes, BUFSIZE - bytes,
@ -616,7 +617,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
NULL, NULL, httpclient); NULL, NULL, httpclient);
if (bytes == -1 || bytes >= (BUFSIZE - 512)) { /* we want at least 512 bytes left */ if (bytes == -1 || bytes >= (BUFSIZE - 512)) { /* we want at least 512 bytes left */
ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error(httpclient, 500, 0, "Header generation failed."); client_send_error_by_id(httpclient, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
fclose(file); fclose(file);
return -1; return -1;
} }
@ -636,7 +637,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
fail: fail:
fclose (file); fclose (file);
client_send_error(httpclient, 416, 1, "Request Range Not Satisfiable\r\n"); client_send_error_by_id(httpclient, ICECAST_ERROR_FSERV_REQUEST_RANGE_NOT_SATISFIABLE);
return -1; return -1;
} }
@ -669,7 +670,7 @@ int fserve_add_client (client_t *client, FILE *file)
ICECAST_LOG_DEBUG("Adding client %p to file serving engine", client); ICECAST_LOG_DEBUG("Adding client %p to file serving engine", client);
if (fclient == NULL) if (fclient == NULL)
{ {
client_send_error(client, 404, 0, "memory exhausted"); client_send_error_by_id(client, ICECAST_ERROR_GEN_MEMORY_EXHAUSTED);
return -1; return -1;
} }
fclient->file = file; fclient->file = file;
@ -691,7 +692,7 @@ void fserve_add_client_callback (client_t *client, fserve_callback_t callback, v
ICECAST_LOG_DEBUG("Adding client to file serving engine"); ICECAST_LOG_DEBUG("Adding client to file serving engine");
if (fclient == NULL) if (fclient == NULL)
{ {
client_send_error(client, 404, 0, "memory exhausted"); client_send_error_by_id(client, ICECAST_ERROR_GEN_MEMORY_EXHAUSTED);
return; return;
} }
fclient->file = NULL; fclient->file = NULL;

View File

@ -8,7 +8,7 @@
* oddsock <oddsock@xiph.org>, * oddsock <oddsock@xiph.org>,
* Karl Heyes <karl@xiph.org>, * Karl Heyes <karl@xiph.org>,
* and others (see AUTHORS for details). * and others (see AUTHORS for details).
* Copyright 2011-2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>, * Copyright 2011-2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
* Copyright 2014, Thomas B. Ruecker <thomas@ruecker.fi>. * Copyright 2014, Thomas B. Ruecker <thomas@ruecker.fi>.
*/ */

View File

@ -8,7 +8,7 @@
* oddsock <oddsock@xiph.org>, * oddsock <oddsock@xiph.org>,
* Karl Heyes <karl@xiph.org> * Karl Heyes <karl@xiph.org>
* and others (see AUTHORS for details). * and others (see AUTHORS for details).
* Copyright 2012-2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>, * Copyright 2012-2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/ */
/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- */
@ -48,6 +48,7 @@
#include "global.h" #include "global.h"
#include "refbuf.h" #include "refbuf.h"
#include "client.h" #include "client.h"
#include "errors.h"
#include "stats.h" #include "stats.h"
#include "logging.h" #include "logging.h"
#include "cfgfile.h" #include "cfgfile.h"
@ -961,10 +962,10 @@ static int _free_client(void *key)
switch (client->respcode) { switch (client->respcode) {
case 0: case 0:
/* if no response has been sent then send a 404 */ /* if no response has been sent then send a 404 */
client_send_error(client, 404, 0, "Mount unavailable"); client_send_error_by_id(client, ICECAST_ERROR_SOURCE_MOUNT_UNAVAILABLE);
break; break;
case 500: case 500:
client_send_error(client, 500, 0, "Stream preparation error"); client_send_error_by_id(client, ICECAST_ERROR_SOURCE_STREAM_PREPARATION_ERROR);
break; break;
default: default:
client_destroy(client); client_destroy(client);

View File

@ -5,7 +5,7 @@
* oddsock <oddsock@xiph.org>, * oddsock <oddsock@xiph.org>,
* Karl Heyes <karl@xiph.org> * Karl Heyes <karl@xiph.org>
* and others (see AUTHORS for details). * and others (see AUTHORS for details).
* Copyright 2012-2015 Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org> * Copyright 2012-2018 Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
* *
* This program is distributed under the GNU General Public License, version 2. * This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source. * A copy of this license is included with this source.
@ -819,13 +819,10 @@ static inline void __free_args(struct __args *arg, size_t len)
size_t i; size_t i;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
free(arg->group); free(arg[i].group);
} }
} }
// Accept: text/html, application/xhtml+xml, */*
// Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
static inline int __parse_q(const char *str) static inline int __parse_q(const char *str)
{ {
int ret = 0; int ret = 0;

View File

@ -5,7 +5,7 @@
* oddsock <oddsock@xiph.org>, * oddsock <oddsock@xiph.org>,
* Karl Heyes <karl@xiph.org> * Karl Heyes <karl@xiph.org>
* and others (see AUTHORS for details). * and others (see AUTHORS for details).
* Copyright 2012-2015 Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org> * Copyright 2012-2018 Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
* *
* This program is distributed under the GNU General Public License, version 2. * This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source. * A copy of this license is included with this source.

View File

@ -8,6 +8,7 @@
* oddsock <oddsock@xiph.org>, * oddsock <oddsock@xiph.org>,
* Karl Heyes <karl@xiph.org> * Karl Heyes <karl@xiph.org>
* and others (see AUTHORS for details). * and others (see AUTHORS for details).
* Copyright 2012-2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -50,6 +51,7 @@
#include "global.h" #include "global.h"
#include "refbuf.h" #include "refbuf.h"
#include "client.h" #include "client.h"
#include "errors.h"
#include "config.h" #include "config.h"
#include "stats.h" #include "stats.h"
#include "fserve.h" #include "fserve.h"
@ -306,7 +308,7 @@ void xslt_transform(xmlDocPtr doc, const char *xslfilename, client_t *client)
{ {
thread_mutex_unlock(&xsltlock); thread_mutex_unlock(&xsltlock);
ICECAST_LOG_ERROR("problem reading stylesheet \"%s\"", xslfilename); ICECAST_LOG_ERROR("problem reading stylesheet \"%s\"", xslfilename);
client_send_error(client, 404, 0, "Could not parse XSLT file"); client_send_error_by_id(client, ICECAST_ERROR_XSLT_PARSE);
return; return;
} }
@ -350,7 +352,7 @@ void xslt_transform(xmlDocPtr doc, const char *xslfilename, client_t *client)
ret = util_http_build_header(refbuf->data, full_len, 0, 0, 200, NULL, mediatype, charset, NULL, NULL, client); ret = util_http_build_header(refbuf->data, full_len, 0, 0, 200, NULL, mediatype, charset, NULL, NULL, client);
if (ret == -1) { if (ret == -1) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error(client, 500, 0, "Header generation failed."); client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
} else { } else {
if ( full_len < (ret + (ssize_t)len + (ssize_t)64) ) { if ( full_len < (ret + (ssize_t)len + (ssize_t)64) ) {
void *new_data; void *new_data;
@ -363,12 +365,12 @@ void xslt_transform(xmlDocPtr doc, const char *xslfilename, client_t *client)
ret = util_http_build_header(refbuf->data, full_len, 0, 0, 200, NULL, mediatype, charset, NULL, NULL, client); ret = util_http_build_header(refbuf->data, full_len, 0, 0, 200, NULL, mediatype, charset, NULL, NULL, client);
if (ret == -1) { if (ret == -1) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error(client, 500, 0, "Header generation failed."); client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
failed = 1; failed = 1;
} }
} else { } else {
ICECAST_LOG_ERROR("Client buffer reallocation failed. Dropping client."); ICECAST_LOG_ERROR("Client buffer reallocation failed. Dropping client.");
client_send_error(client, 500, 0, "Buffer reallocation failed."); client_send_error_by_id(client, ICECAST_ERROR_GEN_BUFFER_REALLOC);
failed = 1; failed = 1;
} }
} }
@ -388,7 +390,7 @@ void xslt_transform(xmlDocPtr doc, const char *xslfilename, client_t *client)
else else
{ {
ICECAST_LOG_WARN("problem applying stylesheet \"%s\"", xslfilename); ICECAST_LOG_WARN("problem applying stylesheet \"%s\"", xslfilename);
client_send_error(client, 404, 0, "XSLT problem"); client_send_error_by_id(client, ICECAST_ERROR_XSLT_problem);
} }
thread_mutex_unlock (&xsltlock); thread_mutex_unlock (&xsltlock);
xmlFreeDoc(res); xmlFreeDoc(res);