[xiph-commits] r18464 - icecast/trunk/icecast/src
ph3-der-loewe at svn.xiph.org
ph3-der-loewe at svn.xiph.org
Tue Jul 17 16:55:09 PDT 2012
Author: ph3-der-loewe
Date: 2012-07-17 16:55:09 -0700 (Tue, 17 Jul 2012)
New Revision: 18464
Modified:
icecast/trunk/icecast/src/admin.c
icecast/trunk/icecast/src/client.c
icecast/trunk/icecast/src/format.c
icecast/trunk/icecast/src/fserve.c
icecast/trunk/icecast/src/util.c
icecast/trunk/icecast/src/util.h
icecast/trunk/icecast/src/xslt.c
Log:
Send proper HTTP headers in responses to clients.
This is currently not implemented for SOURCE and STATS clients as
I suspect to break them. This needs some more research.
close #1639, see #1870 and #1885.
Modified: icecast/trunk/icecast/src/admin.c
===================================================================
--- icecast/trunk/icecast/src/admin.c 2012-07-17 22:02:49 UTC (rev 18463)
+++ icecast/trunk/icecast/src/admin.c 2012-07-17 23:55:09 UTC (rev 18464)
@@ -269,14 +269,19 @@
xmlChar *buff = NULL;
int len = 0;
unsigned int buf_len;
- const char *http = "HTTP/1.0 200 OK\r\n"
- "Content-Type: text/xml\r\n"
- "Content-Length: ";
xmlDocDumpMemory(doc, &buff, &len);
- buf_len = strlen (http) + len + 20;
+ buf_len = len + 256 /* just a random medium number */;
+
client_set_queue (client, NULL);
client->refbuf = refbuf_new (buf_len);
- len = snprintf (client->refbuf->data, buf_len, "%s%d\r\n\r\n%s", http, len, buff);
+
+ /* FIXME: in this section we hope no function will ever return -1 */
+ len = util_http_build_header(client->refbuf->data, buf_len, 0,
+ 0, 200, NULL,
+ "text/xml", NULL,
+ NULL);
+ len += snprintf (client->refbuf->data + len, buf_len - len, "Content-Length: %d\r\n\r\n%s", len, buff);
+
client->refbuf->len = len;
xmlFree(buff);
client->respcode = 200;
@@ -563,11 +568,17 @@
static void html_success(client_t *client, char *message)
{
+ ssize_t ret;
+
+ ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
+ 0, 200, NULL,
+ "text/html", NULL,
+ "");
+ snprintf(client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret,
+ "<html><head><title>Admin request successful</title></head>"
+ "<body><p>%s</p></body></html>", message);
+
client->respcode = 200;
- snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
- "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"
- "<html><head><title>Admin request successful</title></head>"
- "<body><p>%s</p></body></html>", message);
client->refbuf->len = strlen (client->refbuf->data);
fserve_add_client (client, NULL);
}
@@ -693,15 +704,18 @@
const char *username = NULL;
const char *password = NULL;
ice_config_t *config;
+ ssize_t ret;
COMMAND_REQUIRE(client, "username", username);
COMMAND_REQUIRE(client, "password", password);
- client->respcode = 200;
+ ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
+ 0, 200, NULL,
+ "audio/x-mpegurl", NULL,
+ NULL);
+
config = config_get_config();
- snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
- "HTTP/1.0 200 OK\r\n"
- "Content-Type: audio/x-mpegurl\r\n"
+ snprintf (client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret,
"Content-Disposition = attachment; filename=listen.m3u\r\n\r\n"
"http://%s:%s@%s:%d%s\r\n",
username,
@@ -712,6 +726,7 @@
);
config_release_config();
+ client->respcode = 200;
client->refbuf->len = strlen (client->refbuf->data);
fserve_add_client (client, NULL);
}
@@ -1014,8 +1029,10 @@
if (response == PLAINTEXT)
{
- snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
- "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
+ util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
+ 0, 200, NULL,
+ "text/html", NULL,
+ "");
client->refbuf->len = strlen (client->refbuf->data);
client->respcode = 200;
Modified: icecast/trunk/icecast/src/client.c
===================================================================
--- icecast/trunk/icecast/src/client.c 2012-07-17 22:02:49 UTC (rev 18463)
+++ icecast/trunk/icecast/src/client.c 2012-07-17 23:55:09 UTC (rev 18464)
@@ -182,21 +182,32 @@
void client_send_400(client_t *client, char *message) {
- snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
- "HTTP/1.0 400 Bad Request\r\n"
- "Content-Type: text/html\r\n\r\n"
- "<b>%s</b>\r\n", message);
+ ssize_t ret;
+
+ ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
+ 0, 400, NULL,
+ "text/html", NULL,
+ "");
+
+ snprintf(client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret,
+ "<b>%s</b>\r\n", message);
+
client->respcode = 400;
client->refbuf->len = strlen (client->refbuf->data);
fserve_add_client (client, NULL);
}
void client_send_404(client_t *client, char *message) {
+ ssize_t ret;
- snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
- "HTTP/1.0 404 File Not Found\r\n"
- "Content-Type: text/html\r\n\r\n"
- "<b>%s</b>\r\n", message);
+ ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
+ 0, 404, NULL,
+ "text/html", NULL,
+ "");
+
+ snprintf(client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret,
+ "<b>%s</b>\r\n", message);
+
client->respcode = 404;
client->refbuf->len = strlen (client->refbuf->data);
fserve_add_client (client, NULL);
@@ -204,11 +215,10 @@
void client_send_401(client_t *client) {
- snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
- "HTTP/1.0 401 Authentication Required\r\n"
- "WWW-Authenticate: Basic realm=\"Icecast2 Server\"\r\n"
- "\r\n"
- "You need to authenticate\r\n");
+ util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
+ 0, 401, NULL,
+ "text/plain", NULL,
+ "You need to authenticate\r\n");
client->respcode = 401;
client->refbuf->len = strlen (client->refbuf->data);
fserve_add_client (client, NULL);
@@ -216,10 +226,10 @@
void client_send_403(client_t *client, const char *reason)
{
- if (reason == NULL)
- reason = "Forbidden";
- snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
- "HTTP/1.0 403 %s\r\n\r\n", reason);
+ util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
+ 0, 403, reason,
+ "text/plain", NULL,
+ "Forbidden");
client->respcode = 403;
client->refbuf->len = strlen (client->refbuf->data);
fserve_add_client (client, NULL);
Modified: icecast/trunk/icecast/src/format.c
===================================================================
--- icecast/trunk/icecast/src/format.c 2012-07-17 22:02:49 UTC (rev 18463)
+++ icecast/trunk/icecast/src/format.c 2012-07-17 23:55:09 UTC (rev 18464)
@@ -298,8 +298,7 @@
ptr = client->refbuf->data;
client->respcode = 200;
- bytes = snprintf (ptr, remaining, "HTTP/1.0 200 OK\r\n"
- "Content-Type: %s\r\n", source->format->contenttype);
+ bytes = util_http_build_header (ptr, remaining, 0, 0, 200, NULL, source->format->contenttype, NULL, NULL);
remaining -= bytes;
ptr += bytes;
@@ -362,17 +361,6 @@
}
avl_tree_unlock(source->parser->vars);
- config = config_get_config();
- bytes = snprintf (ptr, remaining, "Server: %s\r\n", config->server_id);
- config_release_config();
- remaining -= bytes;
- ptr += bytes;
-
- /* prevent proxy servers from caching */
- bytes = snprintf (ptr, remaining, "Cache-Control: no-cache\r\n");
- remaining -= bytes;
- ptr += bytes;
-
bytes = snprintf (ptr, remaining, "\r\n");
remaining -= bytes;
ptr += bytes;
Modified: icecast/trunk/icecast/src/fserve.c
===================================================================
--- icecast/trunk/icecast/src/fserve.c 2012-07-17 22:02:49 UTC (rev 18463)
+++ icecast/trunk/icecast/src/fserve.c 2012-07-17 23:55:09 UTC (rev 18464)
@@ -454,12 +454,13 @@
*dot = 0;
httpclient->respcode = 200;
+ ret = util_http_build_header (httpclient->refbuf->data, BUFSIZE, 0,
+ 0, 200, NULL,
+ "audio/x-mpegurl", NULL, "");
if (host == NULL)
{
- config = config_get_config();
- snprintf (httpclient->refbuf->data, BUFSIZE,
- "HTTP/1.0 200 OK\r\n"
- "Content-Type: audio/x-mpegurl\r\n\r\n"
+ config = config_get_config();
+ snprintf (httpclient->refbuf->data + ret, BUFSIZE - ret,
"http://%s:%d%s\r\n",
config->hostname, config->port,
sourceuri
@@ -468,9 +469,7 @@
}
else
{
- snprintf (httpclient->refbuf->data, BUFSIZE,
- "HTTP/1.0 200 OK\r\n"
- "Content-Type: audio/x-mpegurl\r\n\r\n"
+ snprintf (httpclient->refbuf->data + ret, BUFSIZE - ret,
"http://%s%s\r\n",
host,
sourceuri
@@ -555,36 +554,27 @@
rangeproblem = 1;
}
if (!rangeproblem) {
- /* Date: is required on all HTTP1.1 responses */
- char currenttime[50];
- time_t now;
- int strflen;
- struct tm result;
off_t endpos = rangenumber+new_content_len-1;
char *type;
if (endpos < 0) {
endpos = 0;
}
- time(&now);
- strflen = strftime(currenttime, 50, "%a, %d-%b-%Y %X GMT",
- gmtime_r(&now, &result));
httpclient->respcode = 206;
type = fserve_content_type (path);
- bytes = snprintf (httpclient->refbuf->data, BUFSIZE,
- "HTTP/1.1 206 Partial Content\r\n"
- "Date: %s\r\n"
+ bytes = util_http_build_header (httpclient->refbuf->data, BUFSIZE, 0,
+ 0, 206, NULL,
+ type, NULL,
+ NULL);
+ bytes += snprintf (httpclient->refbuf->data + bytes, BUFSIZE - bytes,
"Accept-Ranges: bytes\r\n"
"Content-Length: %" PRI_OFF_T "\r\n"
"Content-Range: bytes %" PRI_OFF_T \
- "-%" PRI_OFF_T "/%" PRI_OFF_T "\r\n"
- "Content-Type: %s\r\n\r\n",
- currenttime,
+ "-%" PRI_OFF_T "/%" PRI_OFF_T "\r\n\r\n",
new_content_len,
rangenumber,
endpos,
- content_length,
- type);
+ content_length);
free (type);
}
else {
@@ -598,13 +588,14 @@
else {
char *type = fserve_content_type(path);
httpclient->respcode = 200;
- bytes = snprintf (httpclient->refbuf->data, BUFSIZE,
- "HTTP/1.0 200 OK\r\n"
+ bytes = util_http_build_header (httpclient->refbuf->data, BUFSIZE, 0,
+ 0, 200, NULL,
+ type, NULL,
+ NULL);
+ bytes += snprintf (httpclient->refbuf->data + bytes, BUFSIZE - bytes,
"Accept-Ranges: bytes\r\n"
- "Content-Length: %" PRI_OFF_T "\r\n"
- "Content-Type: %s\r\n\r\n",
- content_length,
- type);
+ "Content-Length: %" PRI_OFF_T "\r\n\r\n",
+ content_length);
free (type);
}
httpclient->refbuf->len = bytes;
Modified: icecast/trunk/icecast/src/util.c
===================================================================
--- icecast/trunk/icecast/src/util.c 2012-07-17 22:02:49 UTC (rev 18463)
+++ icecast/trunk/icecast/src/util.c 2012-07-17 23:55:09 UTC (rev 18464)
@@ -485,6 +485,85 @@
return result;
}
+ssize_t util_http_build_header(char * out, size_t len, ssize_t offset,
+ int cache,
+ int status, const char * statusmsg,
+ const char * contenttype, const char * charset,
+ const char * datablock) {
+ const char * http_version = "1.0";
+ ice_config_t *config;
+ time_t now;
+ struct tm result;
+ char currenttime_buffer[50];
+ char status_buffer[80];
+ char contenttype_buffer[80];
+ ssize_t ret;
+
+ if (!out)
+ return -1;
+
+ if (offset == -1)
+ offset = strlen (out);
+
+ out += offset;
+ len -= offset;
+
+ if (status == -1)
+ {
+ status_buffer[0] = '\0';
+ }
+ else
+ {
+ if (!statusmsg)
+ {
+ switch (status)
+ {
+ case 200: statusmsg = "OK"; break;
+ case 206: statusmsg = "Partial Content"; http_version = "1.1"; break;
+ case 400: statusmsg = "Bad Request"; break;
+ case 401: statusmsg = "Authentication Required"; break;
+ case 403: statusmsg = "Forbidden"; break;
+ case 404: statusmsg = "File Not Found"; break;
+ case 416: statusmsg = "Request Range Not Satisfiable"; break;
+ default: statusmsg = "(unknown status code)"; break;
+ }
+ }
+ snprintf (status_buffer, sizeof (status_buffer), "HTTP/%s %d %s\r\n", http_version, status, statusmsg);
+ }
+
+ if (contenttype)
+ {
+ if (charset)
+ snprintf (contenttype_buffer, sizeof (contenttype_buffer), "Content-Type: %s; charset=%s\r\n",
+ contenttype, charset);
+ else
+ snprintf (contenttype_buffer, sizeof (contenttype_buffer), "Content-Type: %s\r\n",
+ contenttype);
+ }
+ else
+ {
+ contenttype_buffer[0] = '\0';
+ }
+
+ time(&now);
+ strftime(currenttime_buffer, 50, "%a, %d-%b-%Y %X GMT", gmtime_r(&now, &result));
+
+ config = config_get_config();
+ ret = snprintf (out, len, "%sServer: %s\r\nDate: %s\r\n%s%s%s%s%s",
+ status_buffer,
+ config->server_id,
+ currenttime_buffer,
+ contenttype_buffer,
+ (status == 401 ? "WWW-Authenticate: Basic realm=\"Icecast2 Server\"\r\n" : ""),
+ (cache ? "" : "Cache-Control: no-cache\r\n"),
+ (datablock ? "\r\n" : ""),
+ (datablock ? datablock : ""));
+ config_release_config();
+
+ return ret;
+}
+
+
util_dict *util_dict_new(void)
{
return (util_dict *)calloc(1, sizeof(util_dict));
Modified: icecast/trunk/icecast/src/util.h
===================================================================
--- icecast/trunk/icecast/src/util.h 2012-07-17 22:02:49 UTC (rev 18463)
+++ icecast/trunk/icecast/src/util.h 2012-07-17 23:55:09 UTC (rev 18464)
@@ -35,6 +35,33 @@
char *util_url_unescape(const char *src);
char *util_url_escape(const char *src);
+/* Function to build up a HTTP header.
+ * out is the pointer to storage.
+ * len is the total length of out.
+ * offset is the offset in out we should start writing at if offset >= 0.
+ * In this case the 'used' length is len-offset.
+ * If offset is -1 we append at the end of out.
+ * In this case the used length is len-strlen(out).
+ * cache is a bool. If set allow the client to cache the content (static data).
+ * if unset we will send no-caching headers.
+ * status is the HTTP status code. If -1 no HTTP status header is generated.
+ * statusmsg is the status header text. If NULL a default one
+ * is used for the given status code. This is ignored if status is -1.
+ * contenttype is the value for the Content-Type header.
+ * if NULL no such header is generated.
+ * charset is the charset for the object. If NULL no header is generated
+ * or default is used.
+ * datablock is random data added to the request.
+ * If datablock is non NULL the end-of-header is appended as well as this datablock.
+ * If datablock is NULL no end-of-header nor any data is appended.
+ * Returns the number of bytes written or -1 on error.
+ */
+ssize_t util_http_build_header(char * out, size_t len, ssize_t offset,
+ int cache,
+ int status, const char * statusmsg,
+ const char * contenttype, const char * charset,
+ const char * datablock);
+
/* String dictionary type, without support for NULL keys, or multiple
* instances of the same key */
typedef struct _util_dict {
Modified: icecast/trunk/icecast/src/xslt.c
===================================================================
--- icecast/trunk/icecast/src/xslt.c 2012-07-17 22:02:49 UTC (rev 18463)
+++ icecast/trunk/icecast/src/xslt.c 2012-07-17 23:55:09 UTC (rev 18464)
@@ -227,14 +227,16 @@
if (problem == 0)
{
/* the 100 is to allow for the hardcoded headers */
- unsigned int full_len = strlen (mediatype) + len + 100;
+ unsigned int full_len = strlen (mediatype) + len + 256;
refbuf_t *refbuf = refbuf_new (full_len);
+ ssize_t ret;
if (string == NULL)
string = xmlCharStrdup ("");
- snprintf (refbuf->data, full_len,
- "HTTP/1.0 200 OK\r\nContent-Type: %s\r\nContent-Length: %d\r\n\r\n%s",
- mediatype, len, string);
+ ret = util_http_build_header(refbuf->data, full_len, 0, 0, 200, NULL, mediatype, NULL, NULL, NULL);
+ snprintf (refbuf->data + ret, full_len - ret,
+ "Content-Length: %d\r\n\r\n%s",
+ len, string);
client->respcode = 200;
client_set_queue (client, NULL);
More information about the commits
mailing list