[Icecast-dev] [PATCH 22/31] Fix Shoutcast, Move it to a one-pass process
Niv Sardi
nsardi at smartjog.com
Fri Jul 30 07:54:44 PDT 2010
(our function is re-entrant so timeouts are almost automatically handled)
test if we have a shoutcast connection.
stage1, read password, validate it, and prepare in-refbuf with POST (no auth)
get into the normal POST-like loop
Signed-off-by: Niv Sardi <nsardi at smartjog.com>
---
src/connection.c | 180 ++++++++++++++++++++++++------------------------------
1 files changed, 79 insertions(+), 101 deletions(-)
diff --git a/src/connection.c b/src/connection.c
index c66a240..9269ad6 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -116,8 +116,8 @@ cache_file_contents banned_ip, allowed_ip;
rwlock_t _source_shutdown_rwlock;
-static void _handle_shoutcast_compatible (int shoutcast, char *shoutcast_mount);
static int _handle_client (client_t *client);
+static int _handle_shoutcast_stage1 (connection_queue_t *node, char *shoutcast_mount, mount_proxy *mountinfo);
static int _connection_process (connection_queue_t *node);
static void *_connection_thread (void *arg);
@@ -711,19 +711,52 @@ out_fail:
return err;
}
+/* we don't need to clean up on err, as we'll go through the node struct and clean all we have inside */
static int _connection_process (connection_queue_t *node) {
- ice_config_t *config;
- listener_t *listener;
refbuf_t *header;
http_parser_t *parser = NULL;
int hdrsize = 0;
int shoutcast = 0;
int err;
char *shoutcast_mount = NULL;
+ mount_proxy *mountinfo;
+
+ ice_config_t *config;
+ listener_t *listener;
if (!node->refbuf)
node->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE);
header = node->refbuf;
+
+ { /* this code tests for shoutcastness */
+ config = config_get_config();
+ listener = config_get_listen_sock (config, node->con);
+
+ if (listener) {
+ WARN("listner");
+ if (listener->shoutcast_compat)
+ shoutcast = 1;
+ if (listener->ssl && ssl_ok)
+ connection_uses_ssl (node->con);
+ if (listener->shoutcast_mount) {
+ shoutcast_mount = strdup (listener->shoutcast_mount);
+ } else {
+ shoutcast_mount = config->shoutcast_mount;
+ }
+ }
+
+ WARN("shoutcast %d, mount %s", shoutcast, shoutcast_mount);
+
+ mountinfo = config_find_mount (config, shoutcast_mount);
+ config_release_config();
+ }
+
+ if (shoutcast && !header->sync_point) { /* stage2 is actually handled by generic code */
+ err = _handle_shoutcast_stage1 (node, shoutcast_mount, mountinfo);
+ if (err < 0)
+ return err;
+ }
+
hdrsize = util_read_header (node->con, header, HEADER_READ_ENTIRE);
if (hdrsize < 0)
{
@@ -763,42 +796,19 @@ static int _connection_process (connection_queue_t *node) {
err = connection_client_setup (node);
if (err < 0)
return err;
- }
-
- header->len -= hdrsize;
- if (header->len) {
- memmove(header->data, header->data + hdrsize, header->len);
- client_set_queue (node->client, header);
- }
- refbuf_release(header);
-
- config = config_get_config();
- listener = config_get_listen_sock (config, node->con);
- if (listener)
- {
- if (listener->shoutcast_compat)
- shoutcast = 1;
- if (listener->ssl && ssl_ok)
- connection_uses_ssl (node->con);
- if (listener->shoutcast_mount)
- shoutcast_mount = strdup (listener->shoutcast_mount);
- }
- config_release_config();
-
-/* XXX(xaiki): this should be 1, but actually, it's buggy, the client is already up and all.. */
- if (node->con->con_timeout <= time(NULL)) {
- WARN("there might be a bug if you see this");
- client_destroy (node->client);
- return -1;
+ header->len -= hdrsize;
+ if (header->len) {
+ memmove(header->data, header->data + hdrsize, header->len);
+ client_set_queue (node->client, header);
+ }
+ refbuf_release(header);
}
stats_event_inc (NULL, "connections");
- if (shoutcast) {
- _handle_shoutcast_compatible (shoutcast, shoutcast_mount);
- return 0;
- }
+ WARN("shoutcast = %d", shoutcast);
+
return _handle_client (node->client);
}
@@ -1218,81 +1228,49 @@ static void _handle_get_request (client_t *client, char *passed_uri)
if (uri != passed_uri) free (uri);
}
-static void _handle_shoutcast_compatible (int shoutcast, char *shoutcast_mount)
+static int _handle_shoutcast_stage1 (connection_queue_t *node, char *shoutcast_mount, mount_proxy *mountinfo)
{
-/*
- SHOUTCAST IS BROKEN
-*/
- char *http_compliant;
- int http_compliant_len = 0;
- http_parser_t *parser;
- ice_config_t *config = config_get_config ();
- client_t *client = NULL; //node->client;
- refbuf_t *refbuf = client->refbuf;
+ refbuf_t *refbuf = node->refbuf;
+ char *source_password;
+ int err, passlen;
- if (!shoutcast_mount)
- shoutcast_mount = config->shoutcast_mount;
-
- if (shoutcast == 1)
- {
- char *source_password;
- mount_proxy *mountinfo = config_find_mount (config, shoutcast_mount);
- int hdrlen;
+ WARN ("IN");
- if (mountinfo && mountinfo->password)
- source_password = strdup (mountinfo->password);
- else
- source_password = strdup (config->source_password);
+ if (mountinfo && mountinfo->password) {
+ source_password = strdup (mountinfo->password);
+ } else {
+ ice_config_t *config = config_get_config ();
+ source_password = strdup (config->source_password);
config_release_config();
+ }
- if ((hdrlen = util_find_eos_delim (client->refbuf, 0, HEADER_READ_LINE)) < 0) {
- client_destroy (client);
- free (source_password);
- return;
- }
+ passlen = util_read_header (node->con, refbuf, HEADER_READ_LINE);
+ if (passlen <= 0) {
+ WARN ("HEADER READ FAILED");
+ err = passlen;
+ goto out_FAIL;
+ }
- if (memmem (refbuf->data, hdrlen, source_password, strlen(source_password)) != NULL) {
- client->respcode = 200;
- /* send this non-blocking but if there is only a partial write
- * then leave to header timeout */
- sock_write (client->con->sock, "OK2\r\nicy-caps:11\r\n\r\n");
- shoutcast = 2;
- /* we've checked the password, now send it back for reading headers */
-// _add_request_queue (node);
- free (source_password);
- return;
- }
+ if (memmem (refbuf->data, passlen, source_password, strlen(source_password)) == NULL) {
+ INFO ("password does not match (%ld) \"%s\" (%d) \"%s\"",
+ strlen(source_password), source_password, passlen, refbuf->data);
+ err = -ENOENT;
+ goto out_FAIL;
+ }
- INFO1 ("password does not match \"%s\"", refbuf->data);
+/* send this non-blocking but if there is only a partial write
+ * then leave to header timeout */
+ sock_write (node->con->sock, "OK2\r\nicy-caps:11\r\n\r\n");
- client_destroy (client);
- free (source_password);
- return;
- }
- /* actually make a copy as we are dropping the config lock */
- shoutcast_mount = strdup (shoutcast_mount);
- config_release_config();
- /* Here we create a valid HTTP request based of the information
- that was passed in via the non-HTTP style protocol above. This
- means we can use some of our existing code to handle this case */
-// http_compliant_len = 20 + strlen (shoutcast_mount) + node->offset;
- http_compliant = (char *)calloc(1, http_compliant_len);
- snprintf (http_compliant, http_compliant_len,
- "SOURCE %s HTTP/1.0\r\n%s", shoutcast_mount, refbuf->data);
- parser = httpp_create_parser();
- httpp_initialize(parser, NULL);
- if (httpp_parse (parser, http_compliant, strlen(http_compliant)))
- {
- client->parser = parser;
- source_startup (client, shoutcast_mount, SHOUTCAST_SOURCE_AUTH);
- }
- else {
- httpp_destroy (parser);
- client_destroy (client);
- }
- free (http_compliant);
- free (shoutcast_mount);
- return;
+ refbuf->sync_point = snprintf (refbuf->data, refbuf->len, "POST %s HTTP/1.0\r\n", shoutcast_mount);
+
+ /* we've checked the password, now send it back for reading headers */
+ free (source_password);
+ return 0;
+
+out_FAIL:
+ free (source_password);
+ return err;
}
static int _handle_client (client_t *client)
--
1.7.1
More information about the Icecast-dev
mailing list