Commit 55b63780 authored by Philipp Schafft's avatar Philipp Schafft 🦁

Cleanup: Unified code sending responses to client some

parent 33c9d81c
Pipeline #2187 canceled with stage
......@@ -469,15 +469,13 @@ void admin_send_response(xmlDocPtr doc,
const char *xslt_template)
{
if (response == ADMIN_FORMAT_RAW || response == ADMIN_FORMAT_JSON) {
xmlChar *buff = NULL;
int len = 0;
size_t buf_len;
ssize_t ret;
const char *content_type;
if (response == ADMIN_FORMAT_RAW) {
xmlChar *buff = NULL;
int len = 0;
xmlDocDumpMemory(doc, &buff, &len);
content_type = "text/xml";
client_send_buffer(client, 200, "text/xml", "utf-8", (const char *)buff, len, NULL);
xmlFree(buff);
} else {
xmlNodePtr xmlroot = xmlDocGetRootElement(doc);
const char *ns;
......@@ -490,64 +488,10 @@ void admin_send_response(xmlDocPtr doc,
}
json = xml2json_render_doc_simple(doc, ns);
buff = xmlStrdup(XMLSTR(json));
len = strlen(json);
client_send_buffer(client, 200, "application/json", "utf-8", json, -1, NULL);
free(json);
content_type = "application/json";
}
buf_len = len + 1024;
if (buf_len < 4096)
buf_len = 4096;
client_set_queue(client, NULL);
client->refbuf = refbuf_new(buf_len);
ret = util_http_build_header(client->refbuf->data, buf_len, 0,
0, 200, NULL,
content_type, "utf-8",
NULL, NULL, client);
if (ret < 0) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
xmlFree(buff);
return;
} else if (buf_len < (size_t)(len + ret + 64)) {
void *new_data;
buf_len = ret + len + 64;
new_data = realloc(client->refbuf->data, buf_len);
if (new_data) {
ICECAST_LOG_DEBUG("Client buffer reallocation succeeded.");
client->refbuf->data = new_data;
client->refbuf->len = buf_len;
ret = util_http_build_header(client->refbuf->data, buf_len, 0,
0, 200, NULL,
content_type, "utf-8",
NULL, NULL, client);
if (ret == -1) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
xmlFree(buff);
return;
}
} else {
ICECAST_LOG_ERROR("Client buffer reallocation failed. Dropping client.");
client_send_error_by_id(client, ICECAST_ERROR_GEN_BUFFER_REALLOC);
xmlFree(buff);
return;
}
}
/* FIXME: in this section we hope no function will ever return -1 */
ret += snprintf (client->refbuf->data + ret, buf_len - ret, "Content-Length: %d\r\n\r\n%s", xmlStrlen(buff), buff);
client->refbuf->len = ret;
xmlFree(buff);
client->respcode = 200;
fserve_add_client (client, NULL);
}
if (response == ADMIN_FORMAT_HTML) {
} else if (response == ADMIN_FORMAT_HTML) {
char *fullpath_xslt_template;
size_t fullpath_xslt_template_len;
ice_config_t *config = config_get_config();
......@@ -904,29 +848,13 @@ static void command_buildm3u(client_t *client, source_t *source, admin_format_t
const char *mount = source->mount;
const char *username = NULL;
const char *password = NULL;
ssize_t ret;
char buffer[512];
COMMAND_REQUIRE(client, "username", username);
COMMAND_REQUIRE(client, "password", password);
ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
0, 0, 200, NULL,
"audio/x-mpegurl", NULL,
NULL, NULL, client);
if (ret == -1 || ret >= (PER_CLIENT_REFBUF_SIZE - 512)) {
/* we want at least 512 Byte left for data */
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
return;
}
client_get_baseurl(client, NULL, client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret, username, password, "Content-Disposition: attachment; filename=listen.m3u\r\n\r\n", mount, "\r\n");
client->respcode = 200;
client->refbuf->len = strlen (client->refbuf->data);
fserve_add_client (client, NULL);
client_get_baseurl(client, NULL, buffer, sizeof(buffer), username, password, NULL, mount, "\r\n");
client_send_buffer(client, 200, "audio/x-mpegurl", NULL, buffer, -1, "Content-Disposition: attachment; filename=listen.m3u\r\n");
}
xmlNodePtr admin_add_role_to_authentication(auth_t *auth, xmlNodePtr parent)
......
......@@ -441,34 +441,7 @@ void client_send_101(client_t *client, reuse_t reuse)
void client_send_204(client_t *client)
{
source_t *source;
ssize_t ret;
if (!client)
return;
client->reuse = ICECAST_REUSE_KEEPALIVE;
/* We get a source_t* here as this is likely a reply to OPTIONS and we want
* to have as much infos as possible in that case.
*/
avl_tree_rlock(global.source_tree);
source = source_find_mount_raw(client->uri);
ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
0, 204, NULL,
NULL, NULL,
NULL, source, client);
avl_tree_unlock(global.source_tree);
snprintf(client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret,
"Content-Length: 0\r\n\r\n");
client->respcode = 204;
client->refbuf->len = strlen(client->refbuf->data);
fastevent_emit(FASTEVENT_TYPE_CLIENT_SEND_RESPONSE, FASTEVENT_FLAG_MODIFICATION_ALLOWED, FASTEVENT_DATATYPE_CLIENT, client);
fserve_add_client(client, NULL);
client_send_buffer(client, 204, NULL, NULL, NULL, 0, NULL);
}
void client_send_426(client_t *client, reuse_t reuse)
......@@ -484,7 +457,6 @@ void client_send_426(client_t *client, reuse_t reuse)
}
client->reuse = reuse;
ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
0, 426, NULL,
"text/plain", "utf-8",
......@@ -524,6 +496,110 @@ static inline void client_send_500(client_t *client, const char *message)
client_destroy(client);
}
void client_send_buffer(client_t *client, int status, const char *mediatype, const char *charset, const char *buffer, ssize_t len, const char *extra_headers)
{
source_t *source;
size_t buf_len_ours;
size_t buf_len;
ssize_t ret;
int headerlen;
char header[128];
size_t extra_headers_len;
if (!client)
return;
if (status < 200 || status > 599 || (!buffer && len)) {
client_send_500(client, "BUG.");
return;
}
if (len < 0)
len = strlen(buffer);
if (!extra_headers)
extra_headers = "";
extra_headers_len = strlen(extra_headers);
headerlen = snprintf(header, sizeof(header), "Content-Length: %lld\r\n", (long long int)len);
if (headerlen < 1 || headerlen >= (ssize_t)sizeof(header)) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
}
buf_len_ours = len + headerlen + extra_headers_len + 2;
buf_len = buf_len_ours + 1024;
if (buf_len < 4096)
buf_len = 4096;
client_set_queue(client, NULL);
client->refbuf = refbuf_new(buf_len);
client->reuse = ICECAST_REUSE_KEEPALIVE;
avl_tree_rlock(global.source_tree);
source = source_find_mount_raw(client->uri);
ret = util_http_build_header(client->refbuf->data, buf_len, 0,
0, status, NULL,
mediatype, charset,
NULL, source, client);
if (ret < 0) {
avl_tree_unlock(global.source_tree);
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
return;
} else if (buf_len < (ret + buf_len_ours)) {
void *new_data;
buf_len = buf_len_ours + ret + 64;
new_data = realloc(client->refbuf->data, buf_len);
if (new_data) {
ICECAST_LOG_DEBUG("Client buffer reallocation succeeded.");
client->refbuf->data = new_data;
client->refbuf->len = buf_len;
ret = util_http_build_header(client->refbuf->data, buf_len, 0,
0, status, NULL,
mediatype, charset,
NULL, source, client);
if (ret == -1 || buf_len < (ret + buf_len_ours)) {
avl_tree_unlock(global.source_tree);
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
return;
}
} else {
avl_tree_unlock(global.source_tree);
ICECAST_LOG_ERROR("Client buffer reallocation failed. Dropping client.");
client_send_error_by_id(client, ICECAST_ERROR_GEN_BUFFER_REALLOC);
return;
}
}
avl_tree_unlock(global.source_tree);
memcpy(client->refbuf->data + ret, header, headerlen);
ret += headerlen;
memcpy(client->refbuf->data + ret, extra_headers, extra_headers_len);
ret += extra_headers_len;
memcpy(client->refbuf->data + ret, "\r\n", 2);
ret += 2;
if (len) {
memcpy(client->refbuf->data + ret, buffer, len);
ret += len;
}
client->refbuf->len = ret;
client->respcode = status;
fastevent_emit(FASTEVENT_TYPE_CLIENT_SEND_RESPONSE, FASTEVENT_FLAG_MODIFICATION_ALLOWED, FASTEVENT_DATATYPE_CLIENT, client);
fserve_add_client(client, NULL);
}
void client_send_redirect(client_t *client, const char *uuid, int status, const char *location)
{
_client_send_report(client, uuid, "Redirecting", status, location);
......@@ -585,82 +661,27 @@ void client_send_reportxml(client_t *client, reportxml_t *report, document_domai
}
if (admin_format == ADMIN_FORMAT_RAW || admin_format == ADMIN_FORMAT_JSON) {
xmlChar *buff = NULL;
size_t location_length = 0;
int len = 0;
size_t buf_len;
ssize_t ret;
const char *content_type;
if (admin_format == ADMIN_FORMAT_RAW) {
xmlDocDumpMemory(doc, &buff, &len);
content_type = "text/xml";
} else {
char *json = xml2json_render_doc_simple(doc, NULL);
buff = xmlStrdup(XMLSTR(json));
len = strlen(json);
free(json);
content_type = "application/json";
}
char extra_header[512] = "";
if (location) {
location_length = strlen(location);
}
buf_len = len + location_length + 1024;
if (buf_len < 4096)
buf_len = 4096;
client_set_queue(client, NULL);
client->refbuf = refbuf_new(buf_len);
client->reuse = ICECAST_REUSE_KEEPALIVE;
ret = util_http_build_header(client->refbuf->data, buf_len, 0,
0, status, NULL,
content_type, "utf-8",
NULL, NULL, client);
if (ret < 0) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
xmlFree(buff);
return;
} else if (buf_len < (size_t)(len + location_length + ret + 128)) {
void *new_data;
buf_len = ret + len + 128;
new_data = realloc(client->refbuf->data, buf_len);
if (new_data) {
ICECAST_LOG_DEBUG("Client buffer reallocation succeeded.");
client->refbuf->data = new_data;
client->refbuf->len = buf_len;
ret = util_http_build_header(client->refbuf->data, buf_len, 0,
0, status, NULL,
content_type, "utf-8",
NULL, NULL, client);
if (ret == -1) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
xmlFree(buff);
return;
}
} else {
ICECAST_LOG_ERROR("Client buffer reallocation failed. Dropping client.");
client_send_error_by_id(client, ICECAST_ERROR_GEN_BUFFER_REALLOC);
xmlFree(buff);
int res = snprintf(extra_header, sizeof(extra_header), "Location: %s\r\n", location);
if (res < 0 || res >= (ssize_t)sizeof(extra_header)) {
client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
return;
}
}
/* FIXME: in this section we hope no function will ever return -1 */
if (location) {
ret += snprintf(client->refbuf->data + ret, buf_len - ret, "Location: %s\r\n", location);
if (admin_format == ADMIN_FORMAT_RAW) {
xmlChar *buff = NULL;
int len = 0;
xmlDocDumpMemory(doc, &buff, &len);
client_send_buffer(client, status, "text/xml", "utf-8", (const char *)buff, len, extra_header);
xmlFree(buff);
} else {
char *json = xml2json_render_doc_simple(doc, NULL);
client_send_buffer(client, status, "application/json", "utf-8", json, -1, extra_header);
free(json);
}
ret += snprintf(client->refbuf->data + ret, buf_len - ret, "Content-Length: %d\r\n\r\n%s", xmlStrlen(buff), buff);
client->refbuf->len = ret;
xmlFree(buff);
client->respcode = status;
fastevent_emit(FASTEVENT_TYPE_CLIENT_SEND_RESPONSE, FASTEVENT_FLAG_MODIFICATION_ALLOWED, FASTEVENT_DATATYPE_CLIENT, client);
fserve_add_client (client, NULL);
} else {
char *fullpath_xslt_template;
const char *document_domain_path;
......
......@@ -152,6 +152,7 @@ void client_send_204(client_t *client);
void client_send_426(client_t *client, reuse_t reuse);
void client_send_redirect(client_t *client, const char *uuid, int status, const char *location);
void client_send_reportxml(client_t *client, reportxml_t *report, document_domain_t domain, const char *xsl, admin_format_t admin_format_hint, int status, const char *location);
void client_send_buffer(client_t *client, int status, const char *mediatype, const char *charset, const char *buffer, ssize_t len, const char *extra_headers);
reportxml_t *client_get_reportxml(const char *state_definition, const char *state_akindof, const char *state_text);
admin_format_t client_get_admin_format_by_content_negotiation(client_t *client);
int client_send_bytes (client_t *client, const void *buf, unsigned len);
......
......@@ -369,70 +369,20 @@ void xslt_transform(xmlDocPtr doc, const char *xslfilename, client_t *client, in
}
}
if (problem == 0)
{
ssize_t ret;
int failed = 0;
refbuf_t *refbuf;
size_t location_length = 0;
ssize_t full_len = strlen(mediatype) + (ssize_t)len + (ssize_t)1024;
if (problem == 0) {
char extra_header[512] = "";
if (location) {
location_length = strlen(location);
full_len += location_length;
}
if (full_len < 4096)
full_len = 4096;
refbuf = refbuf_new (full_len);
client->reuse = ICECAST_REUSE_KEEPALIVE;
if (string == NULL)
string = xmlCharStrdup ("");
ret = util_http_build_header(refbuf->data, full_len, 0, 0, status, NULL, mediatype, charset, NULL, NULL, client);
if (ret == -1) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
_send_error(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED, status);
} else {
if ( full_len < (ret + (ssize_t)len + (ssize_t)128) ) {
void *new_data;
full_len = ret + (ssize_t)len + (ssize_t)128;
new_data = realloc(refbuf->data, full_len);
if (new_data) {
ICECAST_LOG_DEBUG("Client buffer reallocation succeeded.");
refbuf->data = new_data;
refbuf->len = full_len;
ret = util_http_build_header(refbuf->data, full_len, 0, 0, status, NULL, mediatype, charset, NULL, NULL, client);
if (ret == -1) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
_send_error(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED, status);
failed = 1;
}
} else {
ICECAST_LOG_ERROR("Client buffer reallocation failed. Dropping client.");
_send_error(client, ICECAST_ERROR_GEN_BUFFER_REALLOC, status);
failed = 1;
}
}
if (!failed) {
/* FIXME: in this section we hope no function will ever return -1 */
if (location) {
ret += snprintf(refbuf->data + ret, full_len - ret, "Location: %s\r\n", location);
}
ret += snprintf(refbuf->data + ret, full_len - ret, "Content-Length: %d\r\n\r\n%s", len, string);
client->respcode = status;
client_set_queue (client, NULL);
client->refbuf = refbuf;
refbuf->len = strlen (refbuf->data);
fserve_add_client (client, NULL);
int res = snprintf(extra_header, sizeof(extra_header), "Location: %s\r\n", location);
if (res < 0 || res >= (ssize_t)sizeof(extra_header)) {
client_send_error_by_id(client, ICECAST_ERROR_GEN_HEADER_GEN_FAILED);
return;
}
}
xmlFree (string);
}
else
{
client_send_buffer(client, status, mediatype, charset, (const char *)string, len, extra_header);
xmlFree(string);
} else {
ICECAST_LOG_WARN("problem applying stylesheet \"%s\"", xslfilename);
_send_error(client, ICECAST_ERROR_XSLT_problem, status);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment