[xiph-commits] r8244 - in icecast/branches/kh/icecast: . doc src
karl at motherfish-iii.xiph.org
karl at motherfish-iii.xiph.org
Mon Nov 22 09:09:43 PST 2004
Author: karl
Date: 2004-11-22 09:09:42 -0800 (Mon, 22 Nov 2004)
New Revision: 8244
Modified:
icecast/branches/kh/icecast/configure.in
icecast/branches/kh/icecast/doc/icecast2_config_file.html
icecast/branches/kh/icecast/src/admin.c
icecast/branches/kh/icecast/src/auth.c
icecast/branches/kh/icecast/src/auth.h
icecast/branches/kh/icecast/src/cfgfile.c
icecast/branches/kh/icecast/src/client.c
icecast/branches/kh/icecast/src/client.h
icecast/branches/kh/icecast/src/connection.c
icecast/branches/kh/icecast/src/format_mp3.c
icecast/branches/kh/icecast/src/fserve.c
icecast/branches/kh/icecast/src/fserve.h
icecast/branches/kh/icecast/src/md5.c
icecast/branches/kh/icecast/src/source.c
icecast/branches/kh/icecast/src/source.h
icecast/branches/kh/icecast/src/stats.c
Log:
various cleanups, small resync and some functions moved to help further
merging.
Modified: icecast/branches/kh/icecast/configure.in
===================================================================
--- icecast/branches/kh/icecast/configure.in 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/configure.in 2004-11-22 17:09:42 UTC (rev 8244)
@@ -101,10 +101,10 @@
enable_curl="yes"
XIPH_VAR_APPEND([XIPH_CPPFLAGS],[$CURL_CFLAGS])
XIPH_VAR_PREPEND([XIPH_LIBS],[$CURL_LIBS])
- ], [ AC_MSG_NOTICE([Your curl dev files are too old (7.10 or above required)])
+ ], [ AC_MSG_NOTICE([Your curl dev files are too old (7.10 or above required), YP disabled])
], [#include <curl/curl.h>
])
- ],[ AC_MSG_NOTICE([libcurl not found])
+ ],[ AC_MSG_NOTICE([libcurl not found, YP disabled])
])
dnl -- YP support --
AC_ARG_ENABLE([yp],
Modified: icecast/branches/kh/icecast/doc/icecast2_config_file.html
===================================================================
--- icecast/branches/kh/icecast/doc/icecast2_config_file.html 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/doc/icecast2_config_file.html 2004-11-22 17:09:42 UTC (rev 8244)
@@ -349,6 +349,7 @@
<intro>/path/to/intro.ogg</intro>
<fallback-mount>/example2.ogg</fallback-mount>
<fallback-override>1</fallback-override>
+ <no-yp>1</no-yp>
<burst-size>65536</burst-size>
<mp3-metadata-interval>8192</mp3-metadata-interval>
<authentication type="htpasswd">
@@ -403,6 +404,12 @@
When enabled, this allows a connecting source client or relay on this mountpoint to move
listening clients back from the fallback mount.
</div>
+<h4>no-yp</h4>
+<div class="indentedbox">
+Setting this option prevents this mountpoint from advertising on YP. The default is 0 so YP
+advertising occurs however you may want to prevent it here if you intend listeners to connect
+to a local relay instead
+</div>
<h4>burst-size</h4>
<div class="indentedbox">
This optional setting allows for providing a burst size which overrides the default burst size
Modified: icecast/branches/kh/icecast/src/admin.c
===================================================================
--- icecast/branches/kh/icecast/src/admin.c 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/src/admin.c 2004-11-22 17:09:42 UTC (rev 8244)
@@ -194,7 +194,10 @@
int response, char *xslt_template);
static void html_write(client_t *client, char *fmt, ...);
-xmlDocPtr admin_build_sourcelist(char *current_source)
+/* build an XML doc containing information about currently running sources.
+ * If a mountpoint is passed then that source will not be added to the XML
+ * doc even if the source is running */
+xmlDocPtr admin_build_sourcelist (const char *mount)
{
avl_node *node;
source_t *source;
@@ -207,16 +210,16 @@
xmlnode = xmlNewDocNode(doc, NULL, "icestats", NULL);
xmlDocSetRootElement(doc, xmlnode);
- if (current_source) {
- xmlNewChild(xmlnode, NULL, "current_source", current_source);
+ if (mount) {
+ xmlNewChild(xmlnode, NULL, "current_source", mount);
}
node = avl_get_first(global.source_tree);
while(node) {
source = (source_t *)node->key;
- if (current_source && strcmp (current_source, source->mount) == 0)
+ if (mount && strcmp (mount, source->mount) == 0)
{
- node = avl_get_next(node);
+ node = avl_get_next (node);
continue;
}
@@ -229,7 +232,7 @@
xmlNewChild (srcnode, NULL, "fallback",
(source->fallback_mount != NULL)?
source->fallback_mount:"");
- snprintf (buf, sizeof(buf), "%ld", source->listeners);
+ snprintf (buf, sizeof(buf), "%u", source->listeners);
xmlNewChild (srcnode, NULL, "listeners", buf);
if (source->running)
{
@@ -664,12 +667,11 @@
int response)
{
xmlDocPtr doc;
- xmlNodePtr node, srcnode;
+ xmlNodePtr node, srcnode, listenernode;
+ client_t *current;
+ char buf[22];
char *userAgent = NULL;
- xmlNodePtr listenernode;
- client_t *current;
time_t now = time(NULL);
- char buf[22];
doc = xmlNewDoc("1.0");
node = xmlNewDocNode(doc, NULL, "icestats", NULL);
@@ -681,7 +683,7 @@
xmlDocSetRootElement(doc, node);
memset(buf, '\000', sizeof(buf));
- snprintf(buf, sizeof(buf)-1, "%ld", source->listeners);
+ snprintf(buf, sizeof(buf)-1, "%u", source->listeners);
xmlNewChild(srcnode, NULL, "Listeners", buf);
current = source->active_clients;
@@ -812,7 +814,6 @@
client_destroy(client);
}
-
static void command_kill_source(client_t *client, source_t *source,
int response)
{
@@ -912,9 +913,9 @@
COMMAND_OPTIONAL(client, "title", title);
COMMAND_OPTIONAL(client, "artist", artist);
- if (strcmp(action, "updinfo") != 0)
+ if (strcmp (action, "updinfo") != 0)
{
- client_send_400(client, "No such action");
+ client_send_400 (client, "No such action");
return;
}
@@ -990,7 +991,6 @@
}
}
-
static void command_stats(client_t *client, int response) {
xmlDocPtr doc;
Modified: icecast/branches/kh/icecast/src/auth.c
===================================================================
--- icecast/branches/kh/icecast/src/auth.c 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/src/auth.c 2004-11-22 17:09:42 UTC (rev 8244)
@@ -30,6 +30,7 @@
#include "source.h"
#include "client.h"
#include "cfgfile.h"
+#include "stats.h"
#include "httpp/httpp.h"
#include "md5.h"
@@ -185,3 +186,173 @@
client_send_401 (client);
}
+
+/* Check whether this client is currently on this mount, the client may be
+ * on either the active or pending lists.
+ * return 1 if ok to add or 0 to prevent
+ */
+static int check_duplicate_logins (source_t *source, client_t *client)
+{
+ auth_t *auth = source->authenticator;
+
+ /* allow multiple authenticated relays */
+ if (client->username == NULL || client->is_slave)
+ return 1;
+
+ if (auth && auth->allow_duplicate_users == 0)
+ {
+ client_t *existing;
+
+ existing = source->active_clients;
+ while (existing)
+ {
+ if (existing->username && strcmp (existing->username, client->username) == 0)
+ return 0;
+ existing = existing->next;
+ }
+ existing = source->pending_clients;
+ while (existing)
+ {
+ if (existing->username && strcmp (existing->username, client->username) == 0)
+ return 0;
+ existing = existing->next;
+ }
+ }
+ return 1;
+}
+
+
+/* The actual add client routine, this requires the source to be locked.
+ * if 0 is returned then the client should not be touched, however if -1
+ * is returned then the caller is responsible for handling the client
+ */
+int add_authenticated_client (source_t *source, client_t *client)
+{
+ if (source->authenticator && check_duplicate_logins (source, client) == 0)
+ return -1;
+ /* lets add the client to the pending list */
+ client->next = source->pending_clients;
+ source->pending_clients = client;
+
+ client->write_to_client = format_http_write_to_client;
+ client->refbuf = refbuf_new (4096);
+
+ sock_set_blocking (client->con->sock, SOCK_NONBLOCK);
+ sock_set_nodelay (client->con->sock);
+ if (source->running == 0 && source->on_demand)
+ {
+ /* enable on-demand relay to start, wake up the slave thread */
+ DEBUG0("kicking off on-demand relay");
+ source->on_demand_req = 1;
+ slave_rescan();
+ }
+ DEBUG1 ("Added client to pending on %s", source->mount);
+ stats_event_inc (NULL, "clients");
+ return 0;
+}
+
+
+/* try to add client to a pending list. return
+ * 0 for success
+ * -1 too many clients
+ * -2 mount needs authentication
+ * -3 mount is unavailable
+ */
+static int _add_client (char *passed_mount, client_t *client, int initial_connection)
+{
+ source_t *source;
+ char *mount = passed_mount;
+
+ while (1)
+ {
+ source = source_find_mount (mount);
+ if (passed_mount != mount)
+ free (mount);
+ if (source == NULL)
+ return -3;
+ if (initial_connection && source->no_mount
+ && strcmp (source->mount, passed_mount) == 0)
+ return -3;
+ thread_mutex_lock (&source->lock);
+
+ if (source->running || source->on_demand)
+ {
+ DEBUG2 ("max on %s is %d", source->mount, source->max_listeners);
+ DEBUG2 ("pending %d, current %d", source->new_listeners, source->listeners);
+ if (source->max_listeners == -1)
+ break;
+ if (client->is_slave)
+ break;
+ if (source->new_listeners + source->listeners < (unsigned int)source->max_listeners)
+ break;
+
+ INFO2 ("max listeners (%d) reached on %s", source->max_listeners, source->mount);
+ if (source->fallback_when_full == 0 || source->fallback_mount == NULL)
+ {
+ thread_mutex_unlock (&source->lock);
+ return -1;
+ }
+ if (source->fallback_mount)
+ mount = strdup (source->fallback_mount);
+ else
+ mount = NULL;
+ }
+
+ thread_mutex_unlock (&source->lock);
+ }
+
+ if (auth_check_client (source, client) != AUTH_OK)
+ {
+ thread_mutex_unlock (&source->lock);
+ INFO0 ("listener failed to authenticate");
+ return -2;
+ }
+ source->new_listeners++;
+
+ thread_mutex_unlock (&source->lock);
+ return 0;
+}
+
+
+void add_client (char *mount, client_t *client)
+{
+ int added = -3;
+
+ if (mount)
+ {
+ if (connection_check_relay_pass(client->parser))
+ {
+ client_as_slave (client);
+ INFO0 ("client connected as slave");
+ }
+ thread_mutex_lock (&move_clients_mutex);
+ avl_tree_rlock (global.source_tree);
+ added = _add_client (mount, client, 1);
+ avl_tree_unlock (global.source_tree);
+ thread_mutex_unlock (&move_clients_mutex);
+ }
+ switch (added)
+ {
+ case -1:
+ /* there may be slaves we can re-direct to */
+ if (slave_redirect (mount, client))
+ break;
+ client_send_404 (client,
+ "Too many clients on this mountpoint. Try again later.");
+ DEBUG1 ("max clients on %s", mount);
+ break;
+ case -2:
+ client_send_401 (client);
+ break;
+ case -3:
+ client_send_404 (client, "The file you requested could not be found");
+ break;
+ default:
+ return;
+ }
+ /* failed client, drop global count */
+ global_lock();
+ global.clients--;
+ global_unlock();
+}
+
Modified: icecast/branches/kh/icecast/src/auth.h
===================================================================
--- icecast/branches/kh/icecast/src/auth.h 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/src/auth.h 2004-11-22 17:09:42 UTC (rev 8244)
@@ -13,12 +13,13 @@
#ifndef __AUTH_H__
#define __AUTH_H__
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
#include "source.h"
#include "client.h"
@@ -54,6 +55,8 @@
void auth_clear(auth_t *authenticator);
int auth_postprocess_client (const char *mount, client_t *client);
void auth_close_client (client_t *client);
+int add_authenticated_client (source_t *source, client_t *client);
+void add_client (char *mount, client_t *client);
#endif
Modified: icecast/branches/kh/icecast/src/cfgfile.c
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.c 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/src/cfgfile.c 2004-11-22 17:09:42 UTC (rev 8244)
@@ -158,7 +158,7 @@
xmlFree(c->access_log);
if (c->error_log && c->error_log != CONFIG_DEFAULT_ERROR_LOG)
xmlFree(c->error_log);
- if (c->shoutcast_mount && c->shoutcast_mount != CONFIG_DEFAULT_SHOUTCAST_MOUNT)
+ if (c->shoutcast_mount && c->shoutcast_mount != CONFIG_DEFAULT_SHOUTCAST_MOUNT)
xmlFree(c->shoutcast_mount);
for(i=0; i < MAX_LISTEN_SOCKETS; i++) {
if (c->listeners[i].bind_address) xmlFree(c->listeners[i].bind_address);
Modified: icecast/branches/kh/icecast/src/client.c
===================================================================
--- icecast/branches/kh/icecast/src/client.c 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/src/client.c 2004-11-22 17:09:42 UTC (rev 8244)
@@ -150,9 +150,8 @@
/* helper function for sending the data to a client */
int client_send_bytes (client_t *client, const void *buf, unsigned len)
{
- int ret;
#ifdef HAVE_AIO
- int err;
+ int ret, err;
struct aiocb *aiocbp = &client->aio;
if (client->pending_io == 0)
@@ -175,16 +174,13 @@
client->pending_io = 0;
#else
- ret = sock_write_bytes (client->con->sock, buf, len);
+ int ret = sock_write_bytes (client->con->sock, buf, len);
#endif
- if (ret < 0)
+ if (ret < 0 && !sock_recoverable (sock_error()))
{
- if (! sock_recoverable (sock_error()))
- {
- DEBUG0 ("Client connection died");
- client->con->error = 1;
- }
+ DEBUG0 ("Client connection died");
+ client->con->error = 1;
}
if (ret > 0)
client->con->sent_bytes += ret;
Modified: icecast/branches/kh/icecast/src/client.h
===================================================================
--- icecast/branches/kh/icecast/src/client.h 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/src/client.h 2004-11-22 17:09:42 UTC (rev 8244)
@@ -24,6 +24,7 @@
#include "connection.h"
#include "refbuf.h"
+#include "httpp/httpp.h"
struct source_tag;
Modified: icecast/branches/kh/icecast/src/connection.c
===================================================================
--- icecast/branches/kh/icecast/src/connection.c 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/src/connection.c 2004-11-22 17:09:42 UTC (rev 8244)
@@ -50,6 +50,7 @@
#include "refbuf.h"
#include "client.h"
#include "stats.h"
+#include "auth.h"
#include "logging.h"
#include "xslt.h"
#include "fserve.h"
Modified: icecast/branches/kh/icecast/src/format_mp3.c
===================================================================
--- icecast/branches/kh/icecast/src/format_mp3.c 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/src/format_mp3.c 2004-11-22 17:09:42 UTC (rev 8244)
@@ -580,7 +580,7 @@
}
-static int format_mp3_create_client_data(source_t *source, client_t *client)
+static int format_mp3_create_client_data(source_t *source, client_t *client)
{
mp3_client_data *client_mp3 = calloc(1,sizeof(mp3_client_data));
mp3_state *source_mp3 = source->format->_state;
Modified: icecast/branches/kh/icecast/src/fserve.c
===================================================================
--- icecast/branches/kh/icecast/src/fserve.c 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/src/fserve.c 2004-11-22 17:09:42 UTC (rev 8244)
@@ -46,6 +46,7 @@
#include "logging.h"
#include "cfgfile.h"
#include "util.h"
+#include "compat.h"
#include "fserve.h"
Modified: icecast/branches/kh/icecast/src/fserve.h
===================================================================
--- icecast/branches/kh/icecast/src/fserve.h 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/src/fserve.h 2004-11-22 17:09:42 UTC (rev 8244)
@@ -14,6 +14,7 @@
#define __FSERVE_H__
#include <stdio.h>
+#include "compat.h"
typedef struct _fserve_t
{
Modified: icecast/branches/kh/icecast/src/md5.c
===================================================================
--- icecast/branches/kh/icecast/src/md5.c 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/src/md5.c 2004-11-22 17:09:42 UTC (rev 8244)
@@ -187,7 +187,7 @@
# define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
-# define MD5STEP(f, w, x, y, z, data, s) do { w += f(x, y, z) + data; w = (w<<s) | (w>>(32-s)); w += x; }while (0)
+# define MD5STEP(f, w, x, y, z, data, s) do { w += f(x, y, z) + data; w = (w<<s) | (w>>(32-s)); w += x; }while(0)
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
Modified: icecast/branches/kh/icecast/src/source.c
===================================================================
--- icecast/branches/kh/icecast/src/source.c 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/src/source.c 2004-11-22 17:09:42 UTC (rev 8244)
@@ -62,6 +62,7 @@
static int _compare_clients(void *compare_arg, void *a, void *b);
static void _parse_audio_info (source_t *source, const char *s);
static void source_shutdown (source_t *source);
+static void process_listeners (source_t *source, int fast_clients_only, int deletion_expected);
#ifdef _WIN32
#define source_run_script(x,y) WARN0("on [dis]connect scripts disabled");
#else
@@ -260,6 +261,7 @@
source->shoutcast_compat = 0;
source->max_listeners = -1;
source->yp_public = 0;
+ source->yp_prevent = 0;
util_dict_free (source->audio_info);
source->audio_info = NULL;
@@ -412,7 +414,6 @@
INFO2 ("passing %d listeners to \"%s\"", count, dest->mount);
dest->new_listeners += count;
- dest->check_pending = 1;
source->listeners = 0;
source->new_listeners = 0;
stats_event (source->mount, "listeners", "0");
@@ -449,7 +450,118 @@
}
}
+/* get some data from the source. The stream data is placed in a refbuf
+ * and sent back, however NULL is also valid as in the case of a short
+ * timeout and there's no data pending.
+ */
+static void get_next_buffer (source_t *source)
+{
+ refbuf_t *refbuf = NULL;
+ int no_delay_count = 0;
+ while (global.running == ICE_RUNNING && source->running)
+ {
+ int fds = 0;
+ time_t current = time(NULL);
+ int delay = 200;
+
+ /* service fast clients but jump out once in a while to check on
+ * normal clients */
+ if (no_delay_count < 10)
+ {
+ if (source->active_clients != source->first_normal_client)
+ {
+ delay = 0;
+ no_delay_count++;
+ }
+ }
+ else
+ return;
+
+ thread_mutex_unlock (&source->lock);
+
+ if (source->con)
+ fds = util_timed_wait_for_fd (source->con->sock, delay);
+ else
+ {
+ thread_sleep (delay*1000);
+ source->last_read = current;
+ }
+
+ /* take the lock */
+ thread_mutex_lock (&source->lock);
+
+ if (source->recheck_settings)
+ {
+ ice_config_t *config = config_get_config();
+ source_update_settings (config, source);
+ config_release_config ();
+ }
+ if (fds < 0)
+ {
+ if (! sock_recoverable (sock_error()))
+ {
+ WARN0 ("Error while waiting on socket, Disconnecting source");
+ source->running = 0;
+ }
+ continue;
+ }
+
+ if (fds == 0)
+ {
+ if (source->last_read + (time_t)source->timeout < current)
+ {
+ WARN0 ("Disconnecting source due to socket timeout");
+ source->running = 0;
+ break;
+ }
+ if (delay == 0)
+ {
+ process_listeners (source, 1, 0);
+ continue;
+ }
+ break;
+ }
+ source->last_read = current;
+ refbuf = source->format->get_buffer (source);
+ if (refbuf)
+ {
+ /* append buffer to the in-flight data queue, */
+ if (source->stream_data == NULL)
+ {
+ source->stream_data = refbuf;
+ source->burst_point = refbuf;
+ source->burst_offset = 0;
+ }
+ if (source->stream_data_tail)
+ source->stream_data_tail->next = refbuf;
+ source->stream_data_tail = refbuf;
+ source->queue_size += refbuf->len;
+ refbuf_addref (refbuf);
+
+ /* move the starting point for new listeners */
+ source->burst_offset += refbuf->len;
+ if (source->burst_offset > source->burst_size)
+ {
+ if (source->burst_point->next)
+ {
+ refbuf_t *to_go = source->burst_point;
+
+ source->burst_offset -= source->burst_point->len;
+ source->burst_point = source->burst_point->next;
+ refbuf_release (to_go);
+ }
+ }
+
+ /* save stream to file */
+ if (source->dumpfile && source->format->write_buf_to_file)
+ source->format->write_buf_to_file (source, refbuf);
+ }
+ break;
+ }
+}
+
+
/* general send routine per listener. The deletion_expected tells us whether
* the last in the queue is about to disappear, so if this client is still
* referring to it after writing then drop the client as it's fallen too far
@@ -572,114 +684,48 @@
}
-/* get some data from the source. The stream data is placed in a refbuf
- * and sent back, however NULL is also valid as in the case of a short
- * timeout and there's no data pending.
- */
-static void get_next_buffer (source_t *source)
+static void process_pending_clients (source_t *source)
{
- refbuf_t *refbuf = NULL;
- int no_delay_count = 0;
+ unsigned count = 0;
+ client_t *client = source->pending_clients;
- while (global.running == ICE_RUNNING && source->running)
+ while (client)
{
- int fds = 0;
- time_t current = time(NULL);
- int delay = 200;
+ client_t *to_go = client;
- /* service fast clients but jump out once in a while to check on
- * normal clients */
- if (no_delay_count < 10)
+ client = client->next;
+ /* trap from when clients have been moved */
+ if (to_go->write_to_client == NULL)
{
- if (source->active_clients != source->first_normal_client)
+ /* trap for client moved to fallback file */
+ if (source->file_only)
{
- delay = 0;
- no_delay_count++;
+ to_go->write_to_client = format_intro_write_to_client;
+ client_set_queue (to_go, refbuf_new(4096));
+ to_go->intro_offset = 0;
+ to_go->pos = 4096;
}
- }
- else
- return;
-
- thread_mutex_unlock (&source->lock);
-
- if (source->con)
- fds = util_timed_wait_for_fd (source->con->sock, delay);
- else
- {
- thread_sleep (delay*1000);
- source->last_read = current;
- }
-
- /* take the lock */
- thread_mutex_lock (&source->lock);
-
- if (source->recheck_settings)
- {
- ice_config_t *config = config_get_config();
- source_update_settings (config, source);
- config_release_config ();
- }
- if (fds < 0)
- {
- if (! sock_recoverable (sock_error()))
+ else
{
- WARN0 ("Problem while waiting on socket, Disconnecting source");
- source->running = 0;
+ to_go->write_to_client = source->format->write_buf_to_client;
+ client_set_queue (to_go, source->stream_data_tail);
}
- continue;
}
- if (fds == 0)
- {
- if (source->last_read + (time_t)source->timeout < current)
- {
- WARN0 ("Disconnecting source due to socket timeout");
- source->running = 0;
- break;
- }
- if (delay == 0)
- {
- process_listeners (source, 1, 0);
- continue;
- }
- break;
- }
- source->last_read = current;
- refbuf = source->format->get_buffer (source);
- if (refbuf)
- {
- /* append buffer to the in-flight data queue, */
- if (source->stream_data == NULL)
- {
- source->stream_data = refbuf;
- source->burst_point = refbuf;
- source->burst_offset = 0;
- }
- if (source->stream_data_tail)
- source->stream_data_tail->next = refbuf;
- source->stream_data_tail = refbuf;
- source->queue_size += refbuf->len;
- refbuf_addref (refbuf);
+ to_go->next = source->active_clients;
+ source->active_clients = to_go;
- /* move the starting point for new listeners */
- source->burst_offset += refbuf->len;
- if (source->burst_offset > source->burst_size)
- {
- if (source->burst_point->next)
- {
- refbuf_t *to_go = source->burst_point;
+ count++;
+ source->new_listeners--;
+ }
+ source->pending_clients = NULL;
+ source->pending_clients_tail = &source->pending_clients;
- source->burst_offset -= source->burst_point->len;
- source->burst_point = source->burst_point->next;
- refbuf_release (to_go);
- }
- }
-
- /* save stream to file */
- if (source->dumpfile && source->format->write_buf_to_file)
- source->format->write_buf_to_file (source, refbuf);
- }
- break;
+ if (count)
+ {
+ DEBUG1("Adding %d client(s)", count);
+ source->listeners += count;
+ stats_event_args (source->mount, "listeners", "%d", source->listeners);
}
}
@@ -785,226 +831,9 @@
}
-/* Check whether this client is currently on this mount, the client may be
- * on either the active or pending lists.
- * return 1 if ok to add or 0 to prevent
- */
-static int check_duplicate_logins (source_t *source, client_t *client)
-{
- auth_t *auth = source->authenticator;
- /* allow multiple authenticated relays */
- if (client->username == NULL || client->is_slave)
- return 1;
-
- if (auth && auth->allow_duplicate_users == 0)
- {
- client_t *existing;
-
- existing = source->active_clients;
- while (existing)
- {
- if (existing->username && strcmp (existing->username, client->username) == 0)
- return 0;
- existing = existing->next;
- }
- existing = source->pending_clients;
- while (existing)
- {
- if (existing->username && strcmp (existing->username, client->username) == 0)
- return 0;
- existing = existing->next;
- }
- }
- return 1;
-}
-
-
-/* The actual add client routine, this requires the source to be locked.
- * if 0 is returned then the client should not be touched, however if -1
- * is returned then the caller is responsible for handling the client
- */
-int add_authenticated_client (source_t *source, client_t *client)
+void source_main (source_t *source)
{
- if (source->authenticator && check_duplicate_logins (source, client) == 0)
- return -1;
- /* lets add the client to the pending list */
- client->next = source->pending_clients;
- source->pending_clients = client;
-
- client->write_to_client = format_http_write_to_client;
- client->refbuf = refbuf_new (4096);
-
- sock_set_blocking (client->con->sock, SOCK_NONBLOCK);
- sock_set_nodelay (client->con->sock);
- if (source->running == 0 && source->on_demand)
- {
- /* enable on-demand relay to start, wake up the slave thread */
- DEBUG0("kicking off on-demand relay");
- source->on_demand_req = 1;
- slave_rescan();
- }
- DEBUG1 ("Added client to pending on %s", source->mount);
- source->check_pending = 1;
- stats_event_inc (NULL, "clients");
- return 0;
-}
-
-
-/* try to add client to a pending list. return
- * 0 for success
- * -1 too many clients
- * -2 mount needs authentication
- * -3 mount is unavailable
- */
-static int _add_client (char *passed_mount, client_t *client, int initial_connection)
-{
- source_t *source;
- char *mount = passed_mount;
-
- while (1)
- {
- source = source_find_mount (mount);
- if (passed_mount != mount)
- free (mount);
- if (source == NULL)
- return -3;
- if (initial_connection && source->no_mount
- && strcmp (source->mount, passed_mount) == 0)
- return -3;
- thread_mutex_lock (&source->lock);
-
- if (source->running || source->on_demand)
- {
- DEBUG2 ("max on %s is %d", source->mount, source->max_listeners);
- DEBUG2 ("pending %d, current %d", source->new_listeners, source->listeners);
- if (source->max_listeners == -1)
- break;
- if (client->is_slave)
- break;
- if (source->new_listeners + source->listeners < source->max_listeners)
- break;
-
- INFO2 ("max listeners (%d) reached on %s", source->max_listeners, source->mount);
- if (source->fallback_when_full == 0 || source->fallback_mount == NULL)
- {
- thread_mutex_unlock (&source->lock);
- return -1;
- }
- if (source->fallback_mount)
- mount = strdup (source->fallback_mount);
- else
- mount = NULL;
- }
-
- thread_mutex_unlock (&source->lock);
- }
-
- if (auth_check_client (source, client) != AUTH_OK)
- {
- thread_mutex_unlock (&source->lock);
- INFO0 ("listener failed to authenticate");
- return -2;
- }
- source->new_listeners++;
-
- thread_mutex_unlock (&source->lock);
- return 0;
-}
-
-
-void add_client (char *mount, client_t *client)
-{
- int added = -3;
-
- if (mount)
- {
- if (connection_check_relay_pass(client->parser))
- {
- client_as_slave (client);
- INFO0 ("client connected as slave");
- }
- thread_mutex_lock (&move_clients_mutex);
- avl_tree_rlock (global.source_tree);
- added = _add_client (mount, client, 1);
- avl_tree_unlock (global.source_tree);
- thread_mutex_unlock (&move_clients_mutex);
- }
- switch (added)
- {
- case -1:
- /* there may be slaves we can re-direct to */
- if (slave_redirect (mount, client))
- break;
- client_send_404 (client,
- "Too many clients on this mountpoint. Try again later.");
- DEBUG1 ("max clients on %s", mount);
- break;
- case -2:
- client_send_401 (client);
- break;
- case -3:
- client_send_404 (client, "The file you requested could not be found");
- break;
- default:
- return;
- }
- /* failed client, drop global count */
- global_lock();
- global.clients--;
- global_unlock();
-}
-
-
-static void process_pending_clients (source_t *source)
-{
- unsigned count = 0;
- client_t *client = source->pending_clients;
-
- while (client)
- {
- client_t *to_go = client;
-
- client = client->next;
- /* trap from when clients have been moved */
- if (to_go->write_to_client == NULL)
- {
- /* trap for client moved to fallback file */
- if (source->file_only)
- {
- to_go->write_to_client = format_intro_write_to_client;
- client_set_queue (to_go, refbuf_new(4096));
- to_go->intro_offset = 0;
- to_go->pos = 4096;
- }
- else
- {
- to_go->write_to_client = source->format->write_buf_to_client;
- client_set_queue (to_go, source->stream_data_tail);
- }
- }
-
- to_go->next = source->active_clients;
- source->active_clients = to_go;
-
- count++;
- source->new_listeners--;
- }
- source->pending_clients = NULL;
- source->pending_clients_tail = &source->pending_clients;
- source->check_pending = 0;
-
- if (count)
- {
- DEBUG1("Adding %d client(s)", count);
- source->listeners += count;
- stats_event_args (source->mount, "listeners", "%d", source->listeners);
- }
-}
-
-
-void source_main(source_t *source)
-{
source_init (source);
while (global.running == ICE_RUNNING && source->running)
@@ -1021,7 +850,7 @@
remove_from_q = 1;
/* add pending clients */
- if (source->check_pending)
+ if (source->pending_clients)
process_pending_clients (source);
process_listeners (source, 0, remove_from_q);
Modified: icecast/branches/kh/icecast/src/source.h
===================================================================
--- icecast/branches/kh/icecast/src/source.h 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/src/source.h 2004-11-22 17:09:42 UTC (rev 8244)
@@ -42,10 +42,9 @@
client_t *active_clients;
client_t *first_normal_client;
- int check_pending;
client_t *pending_clients;
client_t **pending_clients_tail;
- long new_listeners;
+ unsigned int new_listeners;
rwlock_t *shutdown_rwlock;
util_dict *audio_info;
@@ -53,7 +52,7 @@
char *dumpfilename; /* Name of a file to dump incoming stream to */
FILE *dumpfile;
- long listeners;
+ unsigned int listeners;
long max_listeners;
int yp_public;
int yp_prevent;
@@ -104,8 +103,6 @@
void source_move_clients (source_t *source, source_t *dest);
int source_remove_client(void *key);
void source_main(source_t *source);
-void add_client (char *mount, client_t *client);
-int add_authenticated_client (source_t *source, client_t *client);
int source_free_client (source_t *source, client_t *client);
void source_recheck_mounts (void);
Modified: icecast/branches/kh/icecast/src/stats.c
===================================================================
--- icecast/branches/kh/icecast/src/stats.c 2004-11-21 21:43:56 UTC (rev 8243)
+++ icecast/branches/kh/icecast/src/stats.c 2004-11-22 17:09:42 UTC (rev 8244)
@@ -239,10 +239,12 @@
va_end(val);
if (ret < 0 || (unsigned int)ret >= sizeof (buf))
+ {
WARN2 ("problem with formatting %s stat %s",
source==NULL ? "global" : source, name);
- else
- stats_event(source, name, buf);
+ return;
+ }
+ stats_event(source, name, buf);
}
static char *_get_stats(char *source, char *name)
More information about the commits
mailing list