1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2025-01-03 14:56:34 -05:00

sync with master

svn path=/icecast/branches/ph3/icecast/; revision=19301
This commit is contained in:
Philipp Schafft 2014-11-10 11:15:49 +00:00
parent fd897f69af
commit 4eed8fe78d
13 changed files with 385 additions and 43 deletions

View File

@ -3,5 +3,5 @@ Michael Smith <msmith@icecast.org>
oddsock <oddsock@xiph.org> oddsock <oddsock@xiph.org>
Karl Heyes <karl@xiph.org> Karl Heyes <karl@xiph.org>
Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org> Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
Thomas B. "dm8tbr" Ruecker <thomas.rucker@tieto.com> Thomas B. "dm8tbr" Ruecker <thomas@ruecker.fi>
David "oneman" Richards <kradradio@gmail.com> David "oneman" Richards <kradradio@gmail.com>

130
ChangeLog
View File

@ -1,3 +1,133 @@
2014-11-08 16:23:26 dm8tbr
* Applying patch by ph3-der-loewe, HTTP PUT requires content-type
* In case of SOURCE we are lenient and thus quite some source clients
don't send a proper content-type, especially if they only support mp3.
* This was meant to be introduced in 2.4.0 already, sadly we missed it.
* All source clients MUST send proper content-type after migrating to
Icecast HTTP PUT protocol.
2014-11-08 13:34:45 ph3-der-loewe
* Fixed regression introduced in r18356 (CVE-2011-4612): client
duration time is now correctly logged. PRIu64 MUST NOT be used with
log_write_direct() as depending on platform PRIu64 may be using
something not supported by __vsnprintf() of log/log.c.
2014-11-08 12:28:17 ph3-der-loewe
* make use of sizeof() not explicit magic numbers
2014-11-07 23:10:43 ph3-der-loewe
* fixing some compiler warnings
2014-11-07 22:06:06 ph3-der-loewe
* updated some copyright headers
2014-11-07 20:56:04 ph3-der-loewe
* fix for %z on win*. hope it doesn't breaky anything else.
2014-11-07 19:14:28 ph3-der-loewe
* added warnings on empty and default values of <fileserve>,
<hostname>, <location>, <admin> and <server-id>
2014-11-07 11:18:54 ph3-der-loewe
* send errorlog (loglevel WARN) to stderr prior to opening the real
logfiles.
2014-11-07 10:12:24 ph3-der-loewe
* added support for type="" and status="" in <header>
(subelement of <http-headers>).
2014-11-07 02:55:57 ph3-der-loewe
* Added support for <http-headers> within <mount>.
Also support merging of headers (normal mount + default mount).
2014-11-07 01:40:28 ph3-der-loewe
* handle empty strings in config file better. Now empty strings are
handled in: accesslog, errorlog, logdir, webroot, adminroot and
hopefully all kinds of port.
2014-11-07 00:56:02 ph3-der-loewe
* initial patch to allow adding user defined headers
2014-11-06 23:55:58 ph3-der-loewe
* coding style and typo correcion
2014-11-06 12:02:00 dm8tbr
* Be more verbose in case of fileserve off
2014-11-05 10:09:07 dm8tbr
* applied patch to update the default ciphers to be more secure
* tested this successfully against https://www.ssllabs.com/ssltest/
2014-11-03 19:34:10 ph3-der-loewe
* applied patch to disable SSLv3 and SSL compression explicitly
2014-11-02 20:19:29 dm8tbr
* fix JSON status API problems
* Put the last item check into every filtered tag.
* This way we shouldn't run into problems of this type anymore.
* Also it should be easier to customize this way,
if someone wants to filter differently.
2014-10-31 09:00:45 ph3-der-loewe
* rename ICE_LISTEN_QUEUE, ICE_RUNNING and ICE_HALTING
so they have a prefix of ICECAST_
2014-10-31 08:46:58 ph3-der-loewe
* LOG_{ERROR|WARN|INFO|DEBUG}()
-> ICECAST_LOG_{ERROR|WARN|INFO|DEBUG}()
* avoid collision with LOG_INFO that is defined as part of syslog.
2014-10-26 14:03:57 ph3-der-loewe
* make <auth> in <mount type="default"> work if no <mount-name> is
given.
2014-10-23 20:41:38 epirat
* More detailed logging
* Add source IP adress to startup and source exit logging
* Add mountpoint to some log lines
2014-10-18 16:25:29 ph3-der-loewe
* fix warnings, mostly related to win*-builds
2014-10-09 10:39:13 ph3-der-loewe
* Replace the old logging macros with variadic argument macros.
(patch by ePirat)
2014-07-23 16:55:57 dm8tbr
* removed threadpool from example config
it is long gone and unused
2014-07-23 10:20:47 dm8tbr
* Fix autogen.sh to work properly on Mac OS
* Applying patch by ePirat
2014-05-06 05:23:42 dm8tbr 2014-05-06 05:23:42 dm8tbr
* This is Icecast 2.4.0! * This is Icecast 2.4.0!

View File

@ -1,8 +1,8 @@
<!-- <!--
VCLT xslt stylesheet for Icecast 2.3.2 and above VCLT xslt stylesheet for Icecast 2.3.2 and above
based on XSPF xslt stylesheet. based on XSPF xslt stylesheet.
Copyright (C) 2007 Thomas B. Ruecker, tbr@ruecker-itk.de Copyright (C) 2007 Thomas B. Ruecker, <tbr@ruecker.fi>
Copyright (C) 2011 Philipp Schafft, lion@lion.leolix.org Copyright (C) 2011 Philipp Schafft, <lion@lion.leolix.org>
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
<!-- <!--
XSPF xslt stylesheet for Icecast and above XSPF xslt stylesheet for Icecast and above
Copyright (C) 2007 Thomas B. Ruecker, thomas@ruecker.fi Copyright (C) 2007 Thomas B. Ruecker, <thomas@ruecker.fi>
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License

View File

@ -5,6 +5,13 @@
<location>Earth</location> <location>Earth</location>
<admin>icemaster@localhost</admin> <admin>icemaster@localhost</admin>
<!-- IMPORTANT!
Especially for inexperienced users:
Start out by ONLY changing all passwords and restarting Icecast.
For detailed setup instructions please refer to the documentation.
It's also available here: http://icecast.org/docs/
-->
<limits> <limits>
<clients>100</clients> <clients>100</clients>
<sources>2</sources> <sources>2</sources>
@ -28,7 +35,7 @@
<authentication> <authentication>
<!-- Sources log in with username 'source' --> <!-- Sources log in with username 'source' -->
<source-password>hackme</source-password> <source-password>hackme</source-password>
<!-- Relays log in username 'relay' --> <!-- Relays log in with username 'relay' -->
<relay-password>hackme</relay-password> <relay-password>hackme</relay-password>
<!-- Admin logs in with the username given below --> <!-- Admin logs in with the username given below -->
@ -48,11 +55,12 @@
<yp-url-timeout>15</yp-url-timeout> <yp-url-timeout>15</yp-url-timeout>
<yp-url>http://dir.xiph.org/cgi-bin/yp-cgi</yp-url> <yp-url>http://dir.xiph.org/cgi-bin/yp-cgi</yp-url>
</directory> </directory>
--> -->
<!-- This is the hostname other people will use to connect to your server. <!-- This is the hostname other people will use to connect to your server.
It affects mainly the urls generated by Icecast for playlists and yp It affects mainly the urls generated by Icecast for playlists and yp
listings. --> listings. You MUST configure it properly for YP listings to work!
-->
<hostname>localhost</hostname> <hostname>localhost</hostname>
<!-- You may have multiple <listener> elements --> <!-- You may have multiple <listener> elements -->
@ -63,10 +71,34 @@
</listen-socket> </listen-socket>
<!-- <!--
<listen-socket> <listen-socket>
<port>8001</port> <port>8080</port>
</listen-socket>
-->
<!--
<listen-socket>
<port>8443</port>
<ssl>1</ssl>
</listen-socket> </listen-socket>
--> -->
<!-- Global header settings
Headers defined here will be returned for every HTTP request to Icecast.
-->
<http-headers>
<!-- Make Icecast public content/API by default
This will make streams easier embeddable (some HTML5 functionality needs it).
Also it allows direct access to e.g. /status-json.xsl from other sites.
If you don't want this, comment out the following line or read up on CORS.
-->
<header name="Access-Control-Allow-Origin" value="*" />
</http-headers>
<!-- Relaying
You don't need this if you only have one server.
Please refer to the config for a detailed explanation.
-->
<!--<master-server>127.0.0.1</master-server>--> <!--<master-server>127.0.0.1</master-server>-->
<!--<master-server-port>8001</master-server-port>--> <!--<master-server-port>8001</master-server-port>-->
<!--<master-update-interval>120</master-update-interval>--> <!--<master-update-interval>120</master-update-interval>-->
@ -80,7 +112,7 @@
<!-- <!--
<relay> <relay>
<server>127.0.0.1</server> <server>127.0.0.1</server>
<port>8001</port> <port>8080</port>
<mount>/example.ogg</mount> <mount>/example.ogg</mount>
<local-mount>/different.ogg</local-mount> <local-mount>/different.ogg</local-mount>
<on-demand>0</on-demand> <on-demand>0</on-demand>
@ -89,9 +121,31 @@
</relay> </relay>
--> -->
<!-- Only define a <mount> section if you want to use advanced options,
<!-- Mountpoints
Only define <mount> sections if you want to use advanced options,
like alternative usernames or passwords like alternative usernames or passwords
<mount> -->
<!-- Default settings for all mounts that don't have a specific <mount type="normal">.
-->
<!--
<mount type="default">
<public>0</public>
<intro>/server-wide-intro.ogg</intro>
<max-listener-duration>3600</max-listener-duration>
<authentication type="url">
<option name="mount_add" value="http://auth.example.org/stream_start.php"/>
</authentication>
<http-headers>
<header name="foo" value="bar" />
</http-headers>
</mount>
-->
<!-- Normal mounts -->
<!--
<mount type="normal">
<mount-name>/example-complex.ogg</mount-name> <mount-name>/example-complex.ogg</mount-name>
<username>othersource</username> <username>othersource</username>
@ -105,16 +159,22 @@
<fallback-when-full>1</fallback-when-full> <fallback-when-full>1</fallback-when-full>
<intro>/example_intro.ogg</intro> <intro>/example_intro.ogg</intro>
<hidden>1</hidden> <hidden>1</hidden>
<no-yp>1</no-yp> <public>1</public>
<authentication type="htpasswd"> <authentication type="htpasswd">
<option name="filename" value="myauth"/> <option name="filename" value="myauth"/>
<option name="allow_duplicate_users" value="0"/> <option name="allow_duplicate_users" value="0"/>
</authentication> </authentication>
<http-headers>
<header name="Access-Control-Allow-Origin" value="http://webplayer.example.org" />
<header name="baz" value="quux" />
</http-headers>
<on-connect>/home/icecast/bin/stream-start</on-connect> <on-connect>/home/icecast/bin/stream-start</on-connect>
<on-disconnect>/home/icecast/bin/stream-stop</on-disconnect> <on-disconnect>/home/icecast/bin/stream-stop</on-disconnect>
</mount> </mount>
-->
<mount> <!--
<mount type="normal">
<mount-name>/auth_example.ogg</mount-name> <mount-name>/auth_example.ogg</mount-name>
<authentication type="url"> <authentication type="url">
<option name="mount_add" value="http://myauthserver.net/notify_mount.php"/> <option name="mount_add" value="http://myauthserver.net/notify_mount.php"/>
@ -125,13 +185,12 @@
<option name="header_prefix" value="ClientHeader."/> <option name="header_prefix" value="ClientHeader."/>
</authentication> </authentication>
</mount> </mount>
--> -->
<fileserve>1</fileserve> <fileserve>1</fileserve>
<paths> <paths>
<!-- basedir is only used if chroot is enabled --> <!-- basedir is only used if chroot is enabled -->
<basedir>@pkgdatadir@</basedir> <basedir>@pkgdatadir@</basedir>
<!-- Note that if <chroot> is turned on below, these paths must both <!-- Note that if <chroot> is turned on below, these paths must both
@ -147,20 +206,24 @@
--> -->
<!-- <!--
<alias source="/foo" destination="/bar"/> <alias source="/foo" destination="/bar"/>
--> -->
<!-- Aliases: can also be used for simple redirections as well, <!-- Aliases: can also be used for simple redirections as well,
this example will redirect all requests for http://server:port/ to this example will redirect all requests for http://server:port/ to
the status page the status page
--> -->
<alias source="/" destination="/status.xsl"/> <alias source="/" destination="/status.xsl"/>
<!-- The certificate file needs to contain both public and private part.
Both should be PEM encoded.
<ssl-certificate>@pkgdatadir@/icecast.pem</ssl-certificate>
-->
</paths> </paths>
<logging> <logging>
<accesslog>access.log</accesslog> <accesslog>access.log</accesslog>
<errorlog>error.log</errorlog> <errorlog>error.log</errorlog>
<!-- <playlistlog>playlist.log</playlistlog> --> <!-- <playlistlog>playlist.log</playlistlog> -->
<loglevel>3</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error --> <loglevel>3</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
<logsize>10000</logsize> <!-- Max size of a logfile --> <logsize>10000</logsize> <!-- Max size of a logfile -->
<!-- If logarchive is enabled (1), then when logsize is reached <!-- If logarchive is enabled (1), then when logsize is reached
the logfile will be moved to [error|access|playlist].log.DATESTAMP, the logfile will be moved to [error|access|playlist].log.DATESTAMP,
otherwise it will be moved to [error|access|playlist].log.old. otherwise it will be moved to [error|access|playlist].log.old.

View File

@ -1,5 +1,6 @@
<!-- This config file contains a minimal set of configurable parameters, <!-- This config file contains a minimal set of configurable parameters,
and mostly just contains the things you need to change. We created and mostly just contains the things you need to change or are
necessary to get Icecast working for most use cases. We created
this for those who got scared away from the rather large and heavily this for those who got scared away from the rather large and heavily
commented icecast.xml.dist file. --> commented icecast.xml.dist file. -->
<icecast> <icecast>
@ -30,6 +31,9 @@
<logging> <logging>
<accesslog>access.log</accesslog> <accesslog>access.log</accesslog>
<errorlog>error.log</errorlog> <errorlog>error.log</errorlog>
<loglevel>3</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error --> <loglevel>3</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
</logging> </logging>
<http-headers>
<header name="Access-Control-Allow-Origin" value="*" />
</http-headers>
</icecast> </icecast>

View File

@ -277,21 +277,57 @@ void admin_send_response (xmlDocPtr doc, client_t *client,
{ {
xmlChar *buff = NULL; xmlChar *buff = NULL;
int len = 0; int len = 0;
unsigned int buf_len; size_t buf_len;
ssize_t ret;
xmlDocDumpMemory(doc, &buff, &len); xmlDocDumpMemory(doc, &buff, &len);
buf_len = len + 256 /* just a random medium number */;
buf_len = len + 1024;
if (buf_len < 4096)
buf_len = 4096;
client_set_queue (client, NULL); client_set_queue (client, NULL);
client->refbuf = refbuf_new (buf_len); client->refbuf = refbuf_new (buf_len);
/* FIXME: in this section we hope no function will ever return -1 */ ret = util_http_build_header(client->refbuf->data, buf_len, 0,
len = util_http_build_header(client->refbuf->data, buf_len, 0,
0, 200, NULL, 0, 200, NULL,
"text/xml", "utf-8", "text/xml", "utf-8",
NULL, NULL); NULL, NULL);
len += snprintf (client->refbuf->data + len, buf_len - len, "Content-Length: %d\r\n\r\n%s", xmlStrlen(buff), buff); if (ret == -1) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_500(client, "Header generation failed.");
xmlFree(buff);
return;
} else if (buf_len < (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,
"text/xml", "utf-8",
NULL, NULL);
if (ret == -1) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_500(client, "Header generation failed.");
xmlFree(buff);
return;
}
} else {
ICECAST_LOG_ERROR("Client buffer reallocation failed. Dropping client.");
client_send_500(client, "Buffer reallocation failed.");
xmlFree(buff);
return;
}
}
client->refbuf->len = len; /* 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); xmlFree(buff);
client->respcode = 200; client->respcode = 200;
fserve_add_client (client, NULL); fserve_add_client (client, NULL);
@ -589,6 +625,13 @@ static void html_success(client_t *client, char *message)
0, 200, NULL, 0, 200, NULL,
"text/html", "utf-8", "text/html", "utf-8",
"", NULL); "", NULL);
if (ret == -1 || ret >= PER_CLIENT_REFBUF_SIZE) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_500(client, "Header generation failed.");
return;
}
snprintf(client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret, snprintf(client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret,
"<html><head><title>Admin request successful</title></head>" "<html><head><title>Admin request successful</title></head>"
"<body><p>%s</p></body></html>", message); "<body><p>%s</p></body></html>", message);
@ -729,6 +772,13 @@ static void command_buildm3u(client_t *client, const char *mount)
"audio/x-mpegurl", NULL, "audio/x-mpegurl", NULL,
NULL, NULL); NULL, NULL);
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_500(client, "Header generation failed.");
return;
}
config = config_get_config(); config = config_get_config();
snprintf (client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret, snprintf (client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret,
"Content-Disposition = attachment; filename=listen.m3u\r\n\r\n" "Content-Disposition = attachment; filename=listen.m3u\r\n\r\n"
@ -1063,10 +1113,17 @@ static void command_list_mounts(client_t *client, int response)
if (response == PLAINTEXT) if (response == PLAINTEXT)
{ {
util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0, ssize_t ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
0, 200, NULL, 0, 200, NULL,
"text/plain", "utf-8", "text/plain", "utf-8",
"", NULL); "", NULL);
if (ret == -1 || ret >= PER_CLIENT_REFBUF_SIZE) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_500(client, "Header generation failed.");
return;
}
client->refbuf->len = strlen (client->refbuf->data); client->refbuf->len = strlen (client->refbuf->data);
client->respcode = 200; client->respcode = 200;

View File

@ -8,8 +8,8 @@
* 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, Thomas B. "dm8tbr" Ruecker <thomas.ruecker@tieto.com>, * Copyright 2011, Dave 'justdave' Miller <justdave@mozilla.com>.
* Dave 'justdave' Miller <justdave@mozilla.com>. * Copyright 2011-2014, Thomas B. "dm8tbr" Ruecker <thomas@ruecker.fi>,
* Copyright 2011-2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>, * Copyright 2011-2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/ */
@ -59,7 +59,7 @@
#define CONFIG_DEFAULT_GROUP NULL #define CONFIG_DEFAULT_GROUP NULL
#define CONFIG_MASTER_UPDATE_INTERVAL 120 #define CONFIG_MASTER_UPDATE_INTERVAL 120
#define CONFIG_YP_URL_TIMEOUT 10 #define CONFIG_YP_URL_TIMEOUT 10
#define CONFIG_DEFAULT_CIPHER_LIST "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS" #define CONFIG_DEFAULT_CIPHER_LIST "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"
#ifndef _WIN32 #ifndef _WIN32
#define CONFIG_DEFAULT_BASE_DIR "/usr/local/icecast" #define CONFIG_DEFAULT_BASE_DIR "/usr/local/icecast"

View File

@ -192,6 +192,12 @@ static void client_send_error(client_t *client, int status, int plain, const cha
plain ? "text/plain" : "text/html", "utf-8", plain ? "text/plain" : "text/html", "utf-8",
plain ? message : "", NULL); plain ? message : "", NULL);
if (ret == -1 || ret >= PER_CLIENT_REFBUF_SIZE) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_500(client, "Header generation failed.");
return;
}
if (!plain) if (!plain)
snprintf(client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret, snprintf(client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret,
"<html><head><title>Error %i</title></head><body><b>%i - %s</b></body></html>\r\n", "<html><head><title>Error %i</title></head><body><b>%i - %s</b></body></html>\r\n",
@ -228,6 +234,21 @@ void client_send_403(client_t *client, const char *message)
client_send_error(client, 403, 1, message); client_send_error(client, 403, 1, message);
} }
/* this function is designed to work even if client is in bad state */
void client_send_500(client_t *client, const char *message) {
const char header[] = "HTTP/1.0 500 Internal Server Error\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n"
"500 - Internal Server Error\n---------------------------\n";
const size_t header_len = sizeof(header) - 1;
int ret;
ret = client_send_bytes(client, header, header_len);
/* only send message if we have one AND if header could have transmitted completly */
if (message && ret == header_len)
client_send_bytes(client, message, strlen(message));
client_destroy(client);
}
/* helper function for sending the data to a client */ /* helper function for sending the data to a client */
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

@ -75,6 +75,7 @@ void client_send_404(client_t *client, const char *message);
void client_send_401(client_t *client); void client_send_401(client_t *client);
void client_send_403(client_t *client, const char *message); void client_send_403(client_t *client, const char *message);
void client_send_400(client_t *client, const char *message); void client_send_400(client_t *client, const char *message);
void client_send_500(client_t *client, const char *message);
int client_send_bytes (client_t *client, const void *buf, unsigned len); int client_send_bytes (client_t *client, const void *buf, unsigned len);
int client_read_bytes (client_t *client, void *buf, unsigned len); int client_read_bytes (client_t *client, void *buf, unsigned len);
void client_set_queue (client_t *client, refbuf_t *refbuf); void client_set_queue (client_t *client, refbuf_t *refbuf);

View File

@ -299,7 +299,29 @@ static int format_prepare_headers (source_t *source, client_t *client)
ptr = client->refbuf->data; ptr = client->refbuf->data;
client->respcode = 200; client->respcode = 200;
bytes = util_http_build_header (ptr, remaining, 0, 0, 200, NULL, source->format->contenttype, NULL, NULL, source); bytes = util_http_build_header(ptr, remaining, 0, 0, 200, NULL, source->format->contenttype, NULL, NULL, source);
if (bytes == -1) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_500(client, "Header generation failed.");
return -1;
} else if ((bytes + 1024) >= remaining) { /* we don't know yet how much to follow but want at least 1kB free space */
void *new_ptr = realloc(ptr, bytes + 1024);
if (new_ptr) {
ICECAST_LOG_DEBUG("Client buffer reallocation succeeded.");
client->refbuf->data = ptr = new_ptr;
client->refbuf->len = remaining = bytes + 1024;
bytes = util_http_build_header(ptr, remaining, 0, 0, 200, NULL, source->format->contenttype, NULL, NULL, source);
if (bytes == -1 ) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_500(client, "Header generation failed.");
return -1;
}
} else {
ICECAST_LOG_ERROR("Client buffer reallocation failed. Dropping client.");
client_send_500(client, "Buffer reallocation failed.");
return -1;
}
}
remaining -= bytes; remaining -= bytes;
ptr += bytes; ptr += bytes;

View File

@ -459,6 +459,11 @@ int fserve_client_create (client_t *httpclient, const char *path)
ret = util_http_build_header (httpclient->refbuf->data, BUFSIZE, 0, ret = util_http_build_header (httpclient->refbuf->data, BUFSIZE, 0,
0, 200, NULL, 0, 200, NULL,
"audio/x-mpegurl", NULL, "", NULL); "audio/x-mpegurl", NULL, "", NULL);
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.");
client_send_500(httpclient, "Header generation failed.");
return -1;
}
if (host == NULL) if (host == NULL)
{ {
config = config_get_config(); config = config_get_config();
@ -568,6 +573,11 @@ int fserve_client_create (client_t *httpclient, const char *path)
0, 206, NULL, 0, 206, NULL,
type, NULL, type, NULL,
NULL, NULL); NULL, NULL);
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.");
client_send_500(httpclient, "Header generation failed.");
return -1;
}
bytes += snprintf (httpclient->refbuf->data + bytes, BUFSIZE - bytes, bytes += snprintf (httpclient->refbuf->data + bytes, BUFSIZE - bytes,
"Accept-Ranges: bytes\r\n" "Accept-Ranges: bytes\r\n"
"Content-Length: %" PRI_OFF_T "\r\n" "Content-Length: %" PRI_OFF_T "\r\n"
@ -594,6 +604,11 @@ int fserve_client_create (client_t *httpclient, const char *path)
0, 200, NULL, 0, 200, NULL,
type, NULL, type, NULL,
NULL, NULL); NULL, NULL);
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.");
client_send_500(httpclient, "Header generation failed.");
return -1;
}
bytes += snprintf (httpclient->refbuf->data + bytes, BUFSIZE - bytes, bytes += snprintf (httpclient->refbuf->data + bytes, BUFSIZE - bytes,
"Accept-Ranges: bytes\r\n" "Accept-Ranges: bytes\r\n"
"Content-Length: %" PRI_OFF_T "\r\n\r\n", "Content-Length: %" PRI_OFF_T "\r\n\r\n",

View File

@ -231,23 +231,52 @@ void xslt_transform(xmlDocPtr doc, const char *xslfilename, client_t *client)
} }
if (problem == 0) if (problem == 0)
{ {
/* the 100 is to allow for the hardcoded headers */ size_t full_len = strlen (mediatype) + len + 1024;
unsigned int full_len = strlen (mediatype) + len + 256;
refbuf_t *refbuf = refbuf_new (full_len); refbuf_t *refbuf = refbuf_new (full_len);
ssize_t ret; ssize_t ret;
int failed = 0;
if (full_len < 4096)
full_len = 4096;
if (string == NULL) if (string == NULL)
string = xmlCharStrdup (""); string = xmlCharStrdup ("");
ret = util_http_build_header(refbuf->data, full_len, 0, 0, 200, NULL, mediatype, charset, NULL, NULL); ret = util_http_build_header(refbuf->data, full_len, 0, 0, 200, NULL, mediatype, charset, NULL, NULL);
snprintf (refbuf->data + ret, full_len - ret, if (ret == -1) {
"Content-Length: %d\r\n\r\n%s", ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
len, string); client_send_500(client, "Header generation failed.");
} else {
if ( full_len < (ret + len + 64) ) {
void *new_data;
full_len = ret + len + 64;
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, 200, NULL, mediatype, charset, NULL, NULL);
if (ret == -1) {
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
client_send_500(client, "Header generation failed.");
failed = 1;
}
} else {
ICECAST_LOG_ERROR("Client buffer reallocation failed. Dropping client.");
client_send_500(client, "Buffer reallocation failed.");
failed = 1;
}
}
client->respcode = 200; if (!failed) {
client_set_queue (client, NULL); snprintf(refbuf->data + ret, full_len - ret, "Content-Length: %d\r\n\r\n%s", len, string);
client->refbuf = refbuf;
refbuf->len = strlen (refbuf->data); client->respcode = 200;
fserve_add_client (client, NULL); client_set_queue (client, NULL);
client->refbuf = refbuf;
refbuf->len = strlen (refbuf->data);
fserve_add_client (client, NULL);
}
}
xmlFree (string); xmlFree (string);
} }
else else