[xiph-commits] r14653 - in icecast/branches/kh/icecast: . src web
karl at svn.xiph.org
karl at svn.xiph.org
Thu Apr 3 08:15:11 PDT 2008
Author: karl
Date: 2008-04-03 08:15:10 -0700 (Thu, 03 Apr 2008)
New Revision: 14653
Modified:
icecast/branches/kh/icecast/NEWS
icecast/branches/kh/icecast/configure.in
icecast/branches/kh/icecast/src/admin.c
icecast/branches/kh/icecast/src/admin.h
icecast/branches/kh/icecast/src/auth.c
icecast/branches/kh/icecast/src/auth_htpasswd.c
icecast/branches/kh/icecast/src/auth_url.c
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/global.h
icecast/branches/kh/icecast/src/slave.c
icecast/branches/kh/icecast/src/slave.h
icecast/branches/kh/icecast/src/source.c
icecast/branches/kh/icecast/src/stats.c
icecast/branches/kh/icecast/src/stats.h
icecast/branches/kh/icecast/web/status2.xsl
Log:
sync work to kh33
Modified: icecast/branches/kh/icecast/NEWS
===================================================================
--- icecast/branches/kh/icecast/NEWS 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/NEWS 2008-04-03 15:15:10 UTC (rev 14653)
@@ -15,6 +15,26 @@
any extra tags are show in the conf/icecast.xml.dist file
+2.3-kh33
+. master/slave update.
+ slave mode only issues a streamlist.txt request if the /admin/slaves request
+ fails. /admin/slaves also acts as an mountpoint for the slave relays by
+ passing a mount= arg and auth.
+ You can now define a <mount> for /admin/slaves to define how slave
+ authentication is done eg url (listener_add) or htpasswd.
+ Once authenticated, the slave can bypass any limits like max listeners etc.
+ The slave also allows for defining a <master> tag block instead of <master-*>
+ tags allowed are <username> <password> <server> <port> <redirect> <bind>
+ auth url can take an "icecast-slave: 1" header, which makes client act as a
+ slave and bypass mount limits.
+. build fixups for OpenBSD and cases where IPV6_V6ONLY is missing
+. move 'clients' limit check to after admin request check, means admin commands
+ can work even if the limit is reached. removes a lock taken as well.
+. drop connections to known slave relays if we find that the destination source
+ is a fallback to file, as this would cause high bandwidth usage.
+. stats fix for inactive on-demand relay stats without a mount definition.
+. added some minor consistency checks.
+
2.3-kh32
. crash fix for a failing on-demand relay.
. incorrect logfile settings for timestamp setting, for playlist and access.log
Modified: icecast/branches/kh/icecast/configure.in
===================================================================
--- icecast/branches/kh/icecast/configure.in 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/configure.in 2008-04-03 15:15:10 UTC (rev 14653)
@@ -1,4 +1,4 @@
-AC_INIT([Icecast], [2.3-kh32], [karl at xiph.org])
+AC_INIT([Icecast], [2.3-kh33], [karl at xiph.org])
AC_PREREQ(2.59)
AC_CONFIG_SRCDIR(src/main.c)
Modified: icecast/branches/kh/icecast/src/admin.c
===================================================================
--- icecast/branches/kh/icecast/src/admin.c 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/admin.c 2008-04-03 15:15:10 UTC (rev 14653)
@@ -52,7 +52,6 @@
int response);
static void command_stats(client_t *client, const char *filename);
static void command_stats_mount (client_t *client, source_t *source, int response);
-static void command_list_mounts(client_t *client, int response);
static void command_kill_client(client_t *client, source_t *source,
int response);
static void command_manageauth(client_t *client, source_t *source,
@@ -333,6 +332,19 @@
if (connection_check_admin_pass (client->parser))
client->authenticated = 1;
+ /* special case for slaves requesting a streamlist for authenticated relaying */
+ if (strcmp (uri, "streams") == 0)
+ {
+ client->is_slave = 1;
+ auth_add_listener ("/admin/streams", client);
+ return 0;
+ }
+ if (strcmp (uri, "streamlist.txt") == 0)
+ {
+ if (connection_check_relay_pass (client->parser))
+ client->authenticated = 1;
+ }
+
if (mount)
{
/* no auth/stream required for this */
@@ -362,13 +374,6 @@
return 0;
}
- /* no auth/stream required for this */
- if (strcmp (uri, "streamlist.txt") == 0)
- {
- if (connection_check_relay_pass (client->parser))
- client->authenticated = 1;
- }
-
admin_handle_general_request (client, uri);
return 0;
}
@@ -1090,7 +1095,7 @@
}
-static void command_list_mounts(client_t *client, int response)
+void command_list_mounts(client_t *client, int response)
{
DEBUG0("List mounts request");
@@ -1099,6 +1104,7 @@
char *buf;
int remaining = PER_CLIENT_REFBUF_SIZE;
int ret;
+
redirector_update (client);
buf = client->refbuf->data;
@@ -1106,7 +1112,10 @@
"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
client->respcode = 200;
- stats_get_streamlist (buf+ret, remaining-ret);
+ if (strcmp (httpp_getvar (client->parser, HTTPP_VAR_URI), "/admin/streams") == 0)
+ client->refbuf->next = stats_get_streams ();
+ else
+ stats_get_streamlist (buf+ret, remaining-ret);
client->refbuf->len = strlen (client->refbuf->data);
fserve_add_client (client, NULL);
Modified: icecast/branches/kh/icecast/src/admin.h
===================================================================
--- icecast/branches/kh/icecast/src/admin.h 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/admin.h 2008-04-03 15:15:10 UTC (rev 14653)
@@ -26,6 +26,7 @@
TEXT
} admin_response_type;
+void command_list_mounts(client_t *client, int response);
int admin_handle_request (client_t *client, const char *uri);
void admin_mount_request (client_t *client, const char *uri);
void admin_source_listeners (source_t *source, xmlNodePtr node);
Modified: icecast/branches/kh/icecast/src/auth.c
===================================================================
--- icecast/branches/kh/icecast/src/auth.c 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/auth.c 2008-04-03 15:15:10 UTC (rev 14653)
@@ -382,7 +382,7 @@
/* Add client to source if it finds one. If a 0 is returned then the client should not be
- * touched, if the return value is -1 then the it failed to add and should not be touched.
+ * touched, if the return value is -1 then it failed to add and should not be touched.
* If it's a -2 value then the client is still around for any further processing.
*/
static int add_listener_to_source (const char *mount, mount_proxy *mountinfo, client_t *client)
@@ -424,6 +424,11 @@
/* ok, we found a source and it is locked */
if (client->is_slave)
{
+ if (source->client == NULL && source->on_demand == 0)
+ {
+ client_send_403 (client, "Slave relay reading from time unregulated stream");
+ return -1;
+ }
INFO0 ("client is from a slave, bypassing limits");
break;
}
@@ -532,6 +537,22 @@
{
int ret = 0;
+ /* check whether we are processing a streamlist request for slaves */
+ if (strcmp (mount, "/admin/streams") == 0)
+ {
+ if (client->authenticated == 0)
+ {
+ client_send_401 (client, NULL);
+ return 0;
+ }
+ mount = httpp_get_query_param (client->parser, "mount");
+ if (mount == NULL)
+ {
+ command_list_mounts (client, TEXT);
+ return 0;
+ }
+ mountinfo = config_find_mount (config_get_config_unlocked(), mount);
+ }
client->authenticated = 1;
/* Here we are parsing the URI request to see if the extension is .xsl, if
@@ -630,9 +651,10 @@
/* we don't need any more data from the listener, just setup for writing */
client->refbuf->len = PER_CLIENT_REFBUF_SIZE;
- if (connection_check_relay_pass(client->parser))
+ if (connection_check_relay_pass (client->parser))
{
client->is_slave = 1;
+ client->authenticated = 1;
INFO0 ("client connected as slave");
}
config = config_get_config();
@@ -643,7 +665,7 @@
client_send_403 (client, "mountpoint unavailable");
return;
}
- if (mountinfo && mountinfo->auth && mountinfo->auth->authenticate)
+ if (client->authenticated == 0 && mountinfo && mountinfo->auth && mountinfo->auth->authenticate)
{
auth_client *auth_user;
Modified: icecast/branches/kh/icecast/src/auth_htpasswd.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_htpasswd.c 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/auth_htpasswd.c 2008-04-03 15:15:10 UTC (rev 14653)
@@ -26,6 +26,7 @@
#include <sys/stat.h>
#include "auth.h"
+#include "auth_htpasswd.h"
#include "source.h"
#include "client.h"
#include "cfgfile.h"
Modified: icecast/branches/kh/icecast/src/auth_url.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_url.c 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/auth_url.c 2008-04-03 15:15:10 UTC (rev 14653)
@@ -30,6 +30,12 @@
*
* icecast-auth-timelimit: 900
*
+ * A listening client may be a slave relay and as such you may want it to avoid
+ * certain checks like max listeners. Send this header back if to wish icecast
+ * to treat the client as a slave relay.
+ *
+ * icecast-slave: 1
+ *
* On client disconnection another request can be sent to a URL with the POST
* information of
*
@@ -170,6 +176,9 @@
sscanf ((char *)ptr+url->timelimit_header_len, "%u\r\n", &limit);
client->con->discon_time = global.time + limit;
}
+ if (strncasecmp (ptr, "icecast-slave: 1", 16) == 0)
+ client->is_slave =1;
+
if (strncasecmp (ptr, "icecast-auth-message: ", 22) == 0)
{
char *eol;
Modified: icecast/branches/kh/icecast/src/cfgfile.c
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.c 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/cfgfile.c 2008-04-03 15:15:10 UTC (rev 14653)
@@ -869,12 +869,13 @@
{ "username", config_get_str, &config->master_username },
{ "password", config_get_str, &config->master_password },
{ "bind", config_get_str, &config->master_bind },
- { "update-interval", config_get_int, &config->master_update_interval },
+ { "interval", config_get_int, &config->master_update_interval },
{ "relay-auth", config_get_bool, &config->master_relay_auth },
{ "redirect", config_get_bool, &config->master_redirect },
{ NULL, NULL, NULL },
};
+ config->master_relay_auth = 1;
if (parse_xml_tags (node, icecast_tags))
return -1;
Modified: icecast/branches/kh/icecast/src/client.c
===================================================================
--- icecast/branches/kh/icecast/src/client.c 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/client.c 2008-04-03 15:15:10 UTC (rev 14653)
@@ -45,14 +45,11 @@
#define CATMODULE "client"
/* create a client_t with the provided connection and parser details. Return
- * 0 on success, -1 if server limit has been reached. In either case a
- * client_t is returned just in case a message needs to be returned. Should
- * be called with global lock held.
+ * client_t ready for use. Should be called with global lock held.
*/
-int client_create (client_t **c_ptr, connection_t *con, http_parser_t *parser)
+client_t *client_create (connection_t *con, http_parser_t *parser)
{
client_t *client = (client_t *)calloc(1, sizeof(client_t));
- int ret = 0;
if (client == NULL)
abort();
@@ -71,20 +68,6 @@
}
}
}
-
- /* don't do client limit check if on an SSL socket, as that will be an admin request */
- if (not_ssl_connection (con))
- {
- ice_config_t *config = config_get_config ();
-
- if (config->client_limit < global.clients)
- {
- WARN2 ("server client limit reached (%d/%d)", config->client_limit, global.clients);
- ret = -1;
- }
- config_release_config ();
- }
-
stats_event_args (NULL, "clients", "%d", global.clients);
client->con = con;
client->parser = parser;
@@ -92,8 +75,7 @@
client->refbuf->len = 0; /* force reader code to ignore buffer contents */
client->pos = 0;
client->write_to_client = format_generic_write_to_client;
- *c_ptr = client;
- return ret;
+ return client;
}
Modified: icecast/branches/kh/icecast/src/client.h
===================================================================
--- icecast/branches/kh/icecast/src/client.h 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/client.h 2008-04-03 15:15:10 UTC (rev 14653)
@@ -87,7 +87,7 @@
struct _client_tag *next;
};
-int client_create (client_t **c_ptr, connection_t *con, http_parser_t *parser);
+client_t *client_create (connection_t *con, http_parser_t *parser);
void client_destroy(client_t *client);
void client_send_504(client_t *client, char *message);
void client_send_416(client_t *client);
@@ -97,8 +97,8 @@
void client_send_403redirect (client_t *client, const char *mount, const char *reason);
void client_send_400(client_t *client, char *message);
void client_send_302(client_t *client, const char *location);
-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_send_bytes (client_t *client, const 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);
#endif /* __CLIENT_H__ */
Modified: icecast/branches/kh/icecast/src/connection.c
===================================================================
--- icecast/branches/kh/icecast/src/connection.c 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/connection.c 2008-04-03 15:15:10 UTC (rev 14653)
@@ -112,7 +112,9 @@
#endif
/* filtering client connection based on IP */
-cache_file_contents banned_ip, allowed_ip, useragents;
+cache_file_contents banned_ip, allowed_ip;
+/* filtering listener connection based on useragent */
+cache_file_contents useragents;
int connection_running = 0;
rwlock_t _source_shutdown_rwlock;
@@ -732,14 +734,7 @@
client_t *client = NULL;
global_lock();
- if (client_create (&client, con, NULL) < 0)
- {
- global_unlock();
- client_send_403 (client, "Icecast connection limit reached");
- /* don't be too eager as this is an imposed hard limit */
- thread_sleep (400000);
- continue;
- }
+ client = client_create (con, NULL);
global_unlock();
if (client->server_conn->ssl && ssl_ok)
@@ -778,8 +773,11 @@
void connection_thread_startup ()
{
- if (conn_tid == NULL)
- conn_tid = thread_create ("connection", connection_thread, NULL, THREAD_ATTACHED);
+ connection_running = 0;
+ while (conn_tid)
+ thread_sleep (100001);
+
+ conn_tid = thread_create ("connection", connection_thread, NULL, THREAD_ATTACHED);
}
void connection_thread_shutdown ()
@@ -1171,6 +1169,7 @@
aliases *alias;
ice_config_t *config;
char *uri = passed_uri;
+ int client_limit_reached = 0;
DEBUG1 ("start with %s", passed_uri);
config = config_get_config();
@@ -1202,6 +1201,11 @@
}
alias = alias->next;
}
+ if (global.clients > config->client_limit)
+ {
+ client_limit_reached = 1;
+ WARN2 ("server client limit reached (%d/%d)", config->client_limit, global.clients);
+ }
config_release_config();
stats_event_inc(NULL, "client_connections");
@@ -1212,7 +1216,11 @@
if (uri != passed_uri) free (uri);
return;
}
- auth_add_listener (uri, client);
+ /* drop non-admin GET requests here if clients limit reached */
+ if (client_limit_reached)
+ client_send_403 (client, "Too many clients connected");
+ else
+ auth_add_listener (uri, client);
if (uri != passed_uri) free (uri);
}
Modified: icecast/branches/kh/icecast/src/global.h
===================================================================
--- icecast/branches/kh/icecast/src/global.h 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/global.h 2008-04-03 15:15:10 UTC (rev 14653)
@@ -50,7 +50,6 @@
/* redirection to slaves */
unsigned int redirect_count;
- struct _redirect_host *redirectors;
spin_t spinlock;
struct rate_calc *out_bitrate;
Modified: icecast/branches/kh/icecast/src/slave.c
===================================================================
--- icecast/branches/kh/icecast/src/slave.c 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/slave.c 2008-04-03 15:15:10 UTC (rev 14653)
@@ -62,6 +62,15 @@
#define CATMODULE "slave"
+typedef struct _redirect_host
+{
+ struct _redirect_host *next;
+ time_t next_update;
+ char *server;
+ int port;
+} redirect_host;
+
+
static void *_slave_thread(void *arg);
static void redirector_add (const char *server, int port, int interval);
static redirect_host *find_slave_host (const char *server, int port);
@@ -74,6 +83,8 @@
static time_t streamlist_check = 0;
static rwlock_t slaves_lock;
+redirect_host *redirectors;
+
relay_server *relay_free (relay_server *relay)
{
relay_server *next = relay->next;
@@ -175,6 +186,7 @@
update_settings = 0;
update_all_mounts = 0;
restart_connection_thread = 0;
+ redirectors = NULL;
#ifndef HAVE_CURL
ERROR0 ("streamlist request disabled, rebuild with libcurl if required");
#endif
@@ -204,8 +216,8 @@
return 0;
}
which=(int) (((float)global.redirect_count)*rand()/(RAND_MAX+1.0)) + 1;
- checking = global.redirectors;
- trail = &global.redirectors;
+ checking = redirectors;
+ trail = &redirectors;
DEBUG2 ("random selection %d (out of %d)", which, global.redirect_count);
while (checking)
@@ -231,7 +243,7 @@
/* add enough for "http://" the port ':' and nul */
int len = strlen (mountpoint) + strlen (checking->server) + 13;
- INFO2 ("redirecting client to slave server "
+ INFO2 ("redirecting listener to slave server "
"at %s:%d", checking->server, checking->port);
location = malloc (len);
snprintf (location, len, "http://%s:%d%s", checking->server,
@@ -320,7 +332,7 @@
"\r\n",
mount,
server_id,
- relay->mp3metadata?"Icy-MetaData: 1\r\n":"",
+ relay->mp3metadata ? "Icy-MetaData: 1\r\n" : "",
auth_header);
memset (header, 0, sizeof(header));
if (util_read_header (con->sock, header, 4096, READ_ENTIRE_HEADER) == 0)
@@ -377,15 +389,7 @@
break;
}
global_lock ();
- if (client_create (&client, con, parser) < 0)
- {
- global_unlock ();
- /* make sure only the client_destory frees these */
- con = NULL;
- parser = NULL;
- client_destroy (client);
- break;
- }
+ client = client_create (con, parser);
global_unlock ();
sock_set_blocking (streamsock, SOCK_NONBLOCK);
client_set_queue (client, NULL);
@@ -524,7 +528,10 @@
{
DEBUG1("Adding relay source at mountpoint \"%s\"", relay->localmount);
if (relay->on_demand)
+ {
+ relay->start = global.time;
slave_update_all_mounts();
+ }
}
else
WARN1 ("new relay but source \"%s\" already exists", relay->localmount);
@@ -548,18 +555,31 @@
source->on_demand = relay->on_demand;
- if (mountinfo && mountinfo->fallback_mount && mountinfo->fallback_override)
+ if (mountinfo)
{
- source_t *fallback;
- avl_tree_rlock (global.source_tree);
- fallback = source_find_mount (mountinfo->fallback_mount);
- if (fallback && fallback->running && fallback->listeners)
+ if (mountinfo->fallback_mount && mountinfo->fallback_override)
{
- DEBUG1 ("fallback running with %lu listeners", fallback->listeners);
- source->on_demand_req = 1;
+ source_t *fallback;
+ avl_tree_rlock (global.source_tree);
+ fallback = source_find_mount (mountinfo->fallback_mount);
+ if (fallback && fallback->running && fallback->listeners)
+ {
+ DEBUG1 ("fallback running with %lu listeners", fallback->listeners);
+ source->on_demand_req = 1;
+ }
+ avl_tree_unlock (global.source_tree);
}
- avl_tree_unlock (global.source_tree);
}
+ else
+ {
+ if (relay->start)
+ {
+ thread_mutex_lock (&relay->source->lock);
+ source_update_settings (config, relay->source, mountinfo);
+ thread_mutex_unlock (&relay->source->lock);
+ relay->start = 0;
+ }
+ }
config_release_config();
if (source->on_demand_req == 0)
break;
@@ -598,6 +618,7 @@
thread_mutex_unlock (&relay->source->lock);
config_release_config ();
stats_event (relay->localmount, "listeners", "0");
+ relay->start = global.time;
}
}
}
@@ -827,13 +848,17 @@
{
relay_server *r = calloc (1, sizeof (relay_server));
relay_server_master *m = calloc (1, sizeof (relay_server_master));
+
m->ip = (char *)xmlStrdup (XMLSTR(master->server));
m->port = master->port;
if (master->bind)
m->bind = (char *)xmlStrdup (XMLSTR(master->bind));
m->mount = (char *)xmlStrdup (XMLSTR(buf));
r->masters = m;
- r->localmount = (char *)xmlStrdup (XMLSTR(buf));
+ if (strncmp (buf, "/admin/streams?mount=/", 22) == 0)
+ r->localmount = (char *)xmlStrdup (XMLSTR(buf+21));
+ else
+ r->localmount = (char *)xmlStrdup (XMLSTR(buf));
r->mp3metadata = 1;
r->on_demand = master->on_demand;
r->interval = master->max_interval;
@@ -874,7 +899,7 @@
port = master->ssl_port;
}
snprintf (auth, sizeof (auth), "%s:%s", master->username, master->password);
- snprintf (url, sizeof (url), "%s://%s:%d/admin/streamlist.txt%s",
+ snprintf (url, sizeof (url), "%s://%s:%d/admin/streams%s",
protocol, master->server, port, master->args);
handle = curl_easy_init ();
curl_easy_setopt (handle, CURLOPT_USERAGENT, master->server_id);
@@ -892,7 +917,14 @@
curl_easy_setopt (handle, CURLOPT_INTERFACE, master->bind);
if (curl_easy_perform (handle) != 0)
- WARN2 ("Failed URL access \"%s\" (%s)", url, error);
+ {
+ /* fall back to traditional request */
+ snprintf (url, sizeof (url), "%s://%s:%d/admin/streamlist.txt%s",
+ protocol, master->server, port, master->args);
+ curl_easy_setopt (handle, CURLOPT_URL, url);
+ if (curl_easy_perform (handle) != 0)
+ WARN2 ("Failed URL access \"%s\" (%s)", url, error);
+ }
if (master->ok)
{
/* process retrieved relays */
@@ -1094,10 +1126,10 @@
static void redirector_clearall (void)
{
thread_rwlock_wlock (&slaves_lock);
- while (global.redirectors)
+ while (redirectors)
{
- redirect_host *current = global.redirectors;
- global.redirectors = current->next;
+ redirect_host *current = redirectors;
+ redirectors = current->next;
INFO2 ("removing %s:%d", current->server, current->port);
free (current->server);
free (current);
@@ -1113,7 +1145,7 @@
redirect_host *redirect;
const char *rserver = httpp_get_query_param (client->parser, "rserver");
const char *value;
- int rport, interval;
+ int rport = 0, interval = 0;
if (rserver==NULL) return;
value = httpp_get_query_param (client->parser, "rport");
@@ -1125,7 +1157,6 @@
interval = atoi (value);
if (interval < 5) return;
-
thread_rwlock_wlock (&slaves_lock);
redirect = find_slave_host (rserver, rport);
if (redirect == NULL)
@@ -1147,7 +1178,7 @@
*/
static redirect_host *find_slave_host (const char *server, int port)
{
- redirect_host *redirect = global.redirectors;
+ redirect_host *redirect = redirectors;
while (redirect)
{
if (strcmp (redirect->server, server) == 0 && redirect->port == port)
@@ -1180,8 +1211,8 @@
redirect->next_update = (time_t)0;
else
redirect->next_update = global.time + interval;
- redirect->next = global.redirectors;
- global.redirectors = redirect;
+ redirect->next = redirectors;
+ redirectors = redirect;
global.redirect_count++;
INFO3 ("slave (%d) at %s:%d added", global.redirect_count,
redirect->server, redirect->port);
Modified: icecast/branches/kh/icecast/src/slave.h
===================================================================
--- icecast/branches/kh/icecast/src/slave.h 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/slave.h 2008-04-03 15:15:10 UTC (rev 14653)
@@ -42,13 +42,6 @@
struct _relay_server *next;
} relay_server;
-typedef struct _redirect_host
-{
- char *server;
- int port;
- time_t next_update;
- struct _redirect_host *next;
-} redirect_host;
void slave_initialize(void);
void slave_shutdown(void);
Modified: icecast/branches/kh/icecast/src/source.c
===================================================================
--- icecast/branches/kh/icecast/src/source.c 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/source.c 2008-04-03 15:15:10 UTC (rev 14653)
@@ -359,6 +359,8 @@
do
{
+ client_t *leave_list = NULL;
+
thread_mutex_lock (&source->lock);
if (source->on_demand == 0 && source->format == NULL)
@@ -381,6 +383,13 @@
client_t *client = source->active_clients;
source->active_clients = client->next;
+ /* don't move known slave relays to streams which are not timed (fallback file) */
+ if (dest->client == NULL && client->is_slave)
+ {
+ client->next = leave_list;
+ leave_list = client;
+ continue;
+ }
/* when switching a client to a different queue, be wary of the
* refbuf it's referring to, if it's http headers then we need
* to write them so don't release it.
@@ -397,14 +406,12 @@
dest->active_clients = client;
count++;
}
- if (count != source->listeners)
- WARN2 ("count %lu, listeners %lu", count, source->listeners);
-
+ source->active_clients = leave_list;
INFO2 ("passing %lu listeners to \"%s\"", count, dest->mount);
dest->listeners += count;
- source->listeners = 0;
- stats_event (source->mount, "listeners", "0");
+ source->listeners -= count;
+ stats_event_args (source->mount, "listeners", "%lu", source->listeners);
} while (0);
@@ -700,6 +707,7 @@
{
client_t *client, **client_p;
client_t *fast_clients = NULL, **fast_client_tail = &fast_clients;
+ unsigned long listener_count = 0;
/* where do we start from */
if (fast_clients_only)
@@ -731,6 +739,7 @@
DEBUG0("Client removed");
continue;
}
+ listener_count++;
if (fast_client && client->check_buffer != format_check_file_buffer)
{
client_t *to_move = client;
@@ -751,6 +760,10 @@
if (fast_clients)
*client_p = fast_clients;
+ /* consistency check, these should match */
+ if (fast_clients_only == 0 && listener_count != source->listeners)
+ ERROR3 ("mount %s has %lu, %lu", source->mount, listener_count, source->listeners);
+
/* has the listener count changed */
if (source->listeners != source->prev_listeners)
{
Modified: icecast/branches/kh/icecast/src/stats.c
===================================================================
--- icecast/branches/kh/icecast/src/stats.c 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/stats.c 2008-04-03 15:15:10 UTC (rev 14653)
@@ -1118,7 +1118,7 @@
if (source->hidden == 0)
{
- if (remaining <= strlen (source->source)+2)
+ if (remaining <= strlen (source->source)+3)
{
WARN0 ("streamlist was truncated");
break;
@@ -1136,6 +1136,51 @@
thread_mutex_unlock (&_stats_mutex);
}
+
+
+/* get a list of refbufs which contain urls for slaves to use for relaying */
+refbuf_t *stats_get_streams (void)
+{
+ avl_node *node;
+ int remaining = 4096;
+ refbuf_t *start = refbuf_new (remaining), *cur = start;
+ const char *pre = "/admin/streams?mount=";
+ char *buffer = cur->data;
+
+ /* now the stats for each source */
+ thread_mutex_lock (&_stats_mutex);
+ node = avl_get_first(_stats.source_tree);
+ while (node)
+ {
+ int ret;
+ stats_source_t *source = (stats_source_t *)node->key;
+
+ if (source->hidden == 0)
+ {
+ if (remaining <= strlen (source->source) + strlen (pre) + 3)
+ {
+ cur->len = 4096 - remaining;
+ cur->next = refbuf_new (4096);
+ remaining = 4096;
+ cur = cur->next;
+ buffer = cur->data;
+ }
+ ret = snprintf (buffer, remaining, "%s%s\r\n", pre, source->source);
+ if (ret > 0)
+ {
+ buffer += ret;
+ remaining -= ret;
+ }
+ }
+ node = avl_get_next(node);
+ }
+ thread_mutex_unlock (&_stats_mutex);
+ cur->len = 4096 - remaining;
+ return start;
+}
+
+
+
/* This removes any source stats from virtual mountpoints, ie mountpoints
* where no source_t exists. This function requires the global sources lock
* to be held before calling.
Modified: icecast/branches/kh/icecast/src/stats.h
===================================================================
--- icecast/branches/kh/icecast/src/stats.h 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/src/stats.h 2008-04-03 15:15:10 UTC (rev 14653)
@@ -77,6 +77,7 @@
void stats_global(ice_config_t *config);
stats_t *stats_get_stats(void);
void stats_get_streamlist (char *buffer, size_t remaining);
+refbuf_t *stats_get_streams (void);
void stats_clear_virtual_mounts (void);
void stats_event(const char *source, const char *name, const char *value);
Modified: icecast/branches/kh/icecast/web/status2.xsl
===================================================================
--- icecast/branches/kh/icecast/web/status2.xsl 2008-04-02 22:38:58 UTC (rev 14652)
+++ icecast/branches/kh/icecast/web/status2.xsl 2008-04-03 15:15:10 UTC (rev 14653)
@@ -1,11 +1,11 @@
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
-<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
+<xsl:output method="text" media-type="text/plain" indent="yes" encoding="UTF-8" />
<xsl:template match = "/icestats" >
<pre>
-MountPoint,Connections,Stream Name,Current Listeners,Description,Currently Playing,Stream URL
-Global,Client:<xsl:value-of select="connections" /> Source: <xsl:value-of select="source_connections" />,,<xsl:value-of select="listeners" />,,
+Global,Clients:<xsl:value-of select="connections" />,Sources:<xsl:value-of select="source_client_connections" />,,<xsl:value-of select="listeners" />,,
+MountPoint,Connections,Stream Name,Current Listeners,Description,Currently Playing,Stream URL
<xsl:for-each select="source">
-<xsl:value-of select="@mount" />,,<xsl:value-of select="name" />,<xsl:value-of select="listeners" />,<xsl:value-of select="description" />,<xsl:value-of select="artist" /> - <xsl:value-of select="title" />,<xsl:value-of select="url" />
+<xsl:value-of select="@mount" />,<xsl:value-of select="listener_connections" />,<xsl:value-of select="server_name" />,<xsl:value-of select="listeners" />,<xsl:value-of select="server_description" />,<xsl:value-of select="artist" /> <xsl:value-of select="title" />,<xsl:value-of select="listenurl" />
</xsl:for-each>
</pre>
</xsl:template>
More information about the commits
mailing list