mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-11-03 04:17:17 -05:00
bump version. mainly an update of 302 work, other bits missed out from before
svn path=/icecast/branches/kh/icecast/; revision=10828
This commit is contained in:
parent
a44c99bd07
commit
a9516a9e31
28
NEWS
28
NEWS
@ -9,8 +9,32 @@ Feature differences from SVN trunk
|
||||
TODO
|
||||
. update slave host handling to add entry via url, as on-demand relays don't
|
||||
connect until there are listeners.
|
||||
. get feedback from people on listener auth via url, Stephen Nixon has done
|
||||
some auth scripts that people can use at http://imux.net/icecast/
|
||||
|
||||
2.3-kh3
|
||||
. add source auth via authenticator, affects certain admin access as well.
|
||||
Only url auth using it currently
|
||||
. relays now have start timestamps, prevents a possible constant rescanning
|
||||
effect with multiple relay failure case
|
||||
. fix memory leak in ogg flac case.
|
||||
. update YP, get bitrate from stats (incoming_bitrate), if not provided. Issue
|
||||
yp add after 60 secs, gives time for bitrates to settle.
|
||||
. cleanups in auth setup, push more setup code into the core auth handler.
|
||||
. when moving listeners, if most recent refbuf is not a sync point then use
|
||||
burst point. Fallback theora streams can be affected by this.
|
||||
. drop master-redirect-port, use <port>.
|
||||
. set <master-redirect> (in slave) non-zero to send IP/port details in
|
||||
streamlist request, so that new listener redirection from master is possible.
|
||||
. set <max-redirect-slaves> (in master) to specify the number of slave servers
|
||||
that can request listener redirection, default 0.
|
||||
. prevent avg/total byte stats for fallback to file sources.
|
||||
. allow for server id to be defined in xml.
|
||||
. add connected stat to source, duration in seconds.
|
||||
. increase average stats for bitrate calculation to 30 seconds
|
||||
. increase sleep duration in connection thread to 100ms
|
||||
. make source clients report read bytes in access.log
|
||||
. bypass clients limit check for ssl connections, let admin do stuff
|
||||
. various type cleanups, gcc4 show various signed/unsigned issues.
|
||||
. sync up with trunk, win32, os.h/compat.h, minor type definitions
|
||||
|
||||
2.3-kh2
|
||||
. merges from post 2.3 release/feedback
|
||||
|
@ -74,7 +74,7 @@
|
||||
<a href="/auth.xsl"><img border="0" src="/images/key.png"/></a> Authentication Required
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<a href="{@mount}.m3u"><img border="0" src="/tunein.png"/></a>
|
||||
<a href="{@mount}.m3u"><img border="0" src="/images/tunein.png"/></a>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
Mount Point : (<xsl:value-of select="@mount" />)
|
||||
|
@ -2,7 +2,6 @@
|
||||
<limits>
|
||||
<clients>100</clients>
|
||||
<sources>2</sources>
|
||||
<threadpool>5</threadpool>
|
||||
<queue-size>524288</queue-size>
|
||||
<client-timeout>30</client-timeout>
|
||||
<header-timeout>15</header-timeout>
|
||||
@ -29,10 +28,6 @@
|
||||
<directory>
|
||||
<yp-url-timeout>15</yp-url-timeout>
|
||||
<yp-url>http://dir.xiph.org/cgi-bin/yp-cgi</yp-url>
|
||||
</directory>
|
||||
<directory>
|
||||
<yp-url-timeout>15</yp-url-timeout>
|
||||
<yp-url>http://www.oddsock.org/cgi-bin/yp-cgi</yp-url>
|
||||
</directory>
|
||||
-->
|
||||
|
||||
@ -69,9 +64,9 @@
|
||||
<!--<relays-on-demand>1</relays-on-demand>-->
|
||||
|
||||
|
||||
<!-- Report <hostname> and this port to master server for redirecting
|
||||
clients to this slave -->
|
||||
<!--<master-redirect-port>8000</master-redirect-port>-->
|
||||
<!-- Request the master server to redirect new listeners to this slave
|
||||
the details passed are based on <hostname> and <port> -->
|
||||
<!--<master-redirect>1</master-redirect>-->
|
||||
|
||||
<!-- Relays. State connection information, and by default
|
||||
request inline metadata for mp3 streams if available.
|
||||
|
@ -1,4 +1,4 @@
|
||||
AC_INIT([Icecast], [2.3-kh2], [karl@xiph.org])
|
||||
AC_INIT([Icecast], [2.3-kh3], [karl@xiph.org])
|
||||
|
||||
AC_PREREQ(2.54)
|
||||
AC_CONFIG_SRCDIR(src/main.c)
|
||||
|
@ -85,6 +85,7 @@ config file. The following shows the list of options available :</p>
|
||||
<mount>
|
||||
<mount-name>/example.ogg</mount-name>
|
||||
<authentication type="url">
|
||||
<option name="stream_auth" value="http://myauthserver.com/stream_auth.php"/>
|
||||
<option name="mount_add" value="http://myauthserver.com/stream_start.php"/>
|
||||
<option name="mount_remove" value="http://myauthserver.com/stream_end.php"/>
|
||||
<option name="listener_add" value="http://myauthserver.com/listener_joined.php"/>
|
||||
@ -98,6 +99,13 @@ config file. The following shows the list of options available :</p>
|
||||
</pre>
|
||||
<p>The options are described below in more detail, each of which is optional, but in each
|
||||
case, within the POST data, the value for each setting is encoded.</p>
|
||||
<h3>stream_auth</h3>
|
||||
<p>This URL is for determining whether a source or admin request is allowed to proceed. This
|
||||
is only used for source client connections and admin requests which apply to sources.</p>
|
||||
<p>POST details are </p>
|
||||
<pre>
|
||||
action=stream_auth&mount=&ip=&server=&port=&user=&pass=%s
|
||||
</pre>
|
||||
<h3>mount_add</h3>
|
||||
<p>This URL is for informing the auth server of a stream starting. No listener information
|
||||
is passed for this, but can be used to initialise any details the auth server may have.
|
||||
|
@ -22,14 +22,37 @@
|
||||
<br />
|
||||
<br />
|
||||
<h2>Setting Up A Master-Slave Relay</h2>
|
||||
<p>In order to setup a relay of this type both servers (the one you wish to relay and the one doing the relaying) need to be icecast2 servers. The following configuration snippet is used as an example:</p>
|
||||
<p>In order to setup a relay of this type both servers (the one you wish to relay and the one
|
||||
doing the relaying) need to be icecast2 servers. The following configuration snippet is used
|
||||
as an example:</p>
|
||||
<pre>
|
||||
<master-server>192.168.1.11</master-server>
|
||||
<master-server-port>8001</master-server-port>
|
||||
<master-update-interval>120</master-update-interval>
|
||||
<master-username>relay</master-username>
|
||||
<master-password>hackme</master-password>
|
||||
</pre>
|
||||
In this example, this configuration is setup in the server which will be doing the relaying (slave server). The master server in this case need not be configured (and actually is unaware of the relaying being performed) as a relay. When the slave server is started, it will connect to the master server located at 192.168.1.11:8001 and will begin to relay all mountpoints connected to the master server. Additionally, every master-update-interval (120 seconds in this case) the slave server will poll the master server to see if any new mountpoints have connected, and if so, the slave server will relay those as well. Note that the names of the mountpoints on the slave server will be identical to those on the master server.
|
||||
<p>In this example, this configuration is setup in the server which will be doing the relaying
|
||||
(slave server). The master server in this case need not be configured (and actually is unaware
|
||||
of the relaying being performed) as a relay. When the slave server is started, it will connect
|
||||
to the master server located at 192.168.1.11:8001 and will begin to relay all non-hidden
|
||||
mountpoints connected to the master server. Additionally, every master-update-interval (120
|
||||
seconds in this case) the slave server will poll the master server to see if any new mountpoints
|
||||
have connected, and if so, the slave server will relay those as well. Note that the names of
|
||||
the mountpoints on the slave server will be identical to those on the master server.</p>
|
||||
<p>To extend on the idea of load sharing, it is possible for a slave icecast2 to communicate
|
||||
certain information to allow for new listeners to be redirected from the master server to the
|
||||
slave. In such cases, the master will send to the listener a HTTP 302 response code with a URL
|
||||
of the slave server which has been randomly selected.</p>
|
||||
</p>To enable this certain settings have to be enabled. In the master</p>
|
||||
<pre>
|
||||
<max-redirect-slaves>5</max-redirect-slaves>
|
||||
</pre>
|
||||
<p>This limits the redirection mechanism to 5 slaves, the default is 0, preventing any attempts
|
||||
to redirect new listeners. In the slave </p>
|
||||
<pre>
|
||||
<master-redirect>1</master-redirect>
|
||||
</pre>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
|
@ -1160,6 +1160,9 @@ static void command_list_mounts(client_t *client, int response)
|
||||
ice_config_t *config = config_get_config ();
|
||||
mount_proxy *mountinfo = config->mounts;
|
||||
|
||||
/* do any redirector updates */
|
||||
redirector_update (client);
|
||||
|
||||
buf = client->refbuf->data;
|
||||
ret = snprintf (buf, remaining,
|
||||
"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
||||
|
@ -410,7 +410,7 @@ static int add_authenticated_listener (const char *mount, mount_proxy *mountinfo
|
||||
DEBUG0 ("client authenticated, passed to source");
|
||||
else
|
||||
{
|
||||
if (slave_redirect (mount, client))
|
||||
if (redirect_client (mount, client))
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
@ -472,7 +472,7 @@ void add_client (const char *mount, client_t *client)
|
||||
|
||||
if (connection_check_relay_pass(client->parser))
|
||||
{
|
||||
client_as_slave (client);
|
||||
client->is_slave = 1;
|
||||
INFO0 ("client connected as slave");
|
||||
}
|
||||
config = config_get_config();
|
||||
|
@ -408,7 +408,7 @@ static void url_stream_auth (auth_client *auth_user)
|
||||
{
|
||||
client_t *client = auth_user->client;
|
||||
auth_url *url = client->auth->state;
|
||||
char *mount, *host, *user, *pass, *ipaddr, *metadata="";
|
||||
char *mount, *host, *user, *pass, *ipaddr, *admin="";
|
||||
char post [4096];
|
||||
|
||||
if (strchr (url->stream_auth, '@') == NULL)
|
||||
@ -426,7 +426,7 @@ static void url_stream_auth (auth_client *auth_user)
|
||||
if (strncmp (auth_user->mount, "/admin/", 7) == 0)
|
||||
{
|
||||
mount = util_url_escape (httpp_get_query_param (client->parser, "mount"));
|
||||
metadata = "&metadata=1";
|
||||
admin = "&admin=1";
|
||||
}
|
||||
else
|
||||
mount = util_url_escape (auth_user->mount);
|
||||
@ -436,8 +436,8 @@ static void url_stream_auth (auth_client *auth_user)
|
||||
ipaddr = util_url_escape (client->con->ip);
|
||||
|
||||
snprintf (post, sizeof (post),
|
||||
"action=stream_auth&mount=%sip=%s&server=%s&port=%d&user=%s&pass=%s%s",
|
||||
mount, ipaddr, host, auth_user->port, user, pass, metadata);
|
||||
"action=stream_auth&mount=%s&ip=%s&server=%s&port=%d&user=%s&pass=%s%s",
|
||||
mount, ipaddr, host, auth_user->port, user, pass, admin);
|
||||
free (ipaddr);
|
||||
free (user);
|
||||
free (pass);
|
||||
|
@ -367,7 +367,6 @@ static void _set_defaults(ice_config_t *configuration)
|
||||
configuration->master_username = (char*)xmlCharStrdup (CONFIG_DEFAULT_MASTER_USERNAME);
|
||||
configuration->master_password = NULL;
|
||||
configuration->master_relay_auth = 0;
|
||||
configuration->master_redirect_port = 0;
|
||||
configuration->base_dir = CONFIG_DEFAULT_BASE_DIR;
|
||||
configuration->log_dir = CONFIG_DEFAULT_LOG_DIR;
|
||||
configuration->webroot_dir = CONFIG_DEFAULT_WEBROOT_DIR;
|
||||
@ -458,10 +457,6 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node,
|
||||
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
configuration->master_server_port = atoi(tmp);
|
||||
xmlFree (tmp);
|
||||
} else if (xmlStrcmp(node->name, XMLSTR ("master-redirect-port")) == 0) {
|
||||
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
configuration->master_redirect_port = atoi(tmp);
|
||||
xmlFree (tmp);
|
||||
} else if (xmlStrcmp(node->name, XMLSTR ("master-update-interval")) == 0) {
|
||||
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
configuration->master_update_interval = atoi(tmp);
|
||||
@ -474,6 +469,14 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node,
|
||||
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
configuration->master_ssl_port = atoi(tmp);
|
||||
xmlFree (tmp);
|
||||
} else if (xmlStrcmp(node->name, XMLSTR ("master-redirect")) == 0) {
|
||||
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
configuration->master_redirect = atoi(tmp);
|
||||
xmlFree (tmp);
|
||||
} else if (xmlStrcmp(node->name, XMLSTR ("max-redirect-slaves")) == 0) {
|
||||
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
configuration->max_redirects = atoi(tmp);
|
||||
xmlFree (tmp);
|
||||
} else if (xmlStrcmp(node->name, XMLSTR ("shoutcast-mount")) == 0) {
|
||||
if (configuration->shoutcast_mount &&
|
||||
configuration->shoutcast_mount != CONFIG_DEFAULT_SHOUTCAST_MOUNT)
|
||||
@ -495,6 +498,8 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node,
|
||||
_parse_security(doc, node->xmlChildrenNode, configuration);
|
||||
}
|
||||
} while ((node = node->next));
|
||||
if (configuration->max_redirects == 0 && configuration->master_redirect)
|
||||
configuration->max_redirects = 1;
|
||||
}
|
||||
|
||||
static void _parse_limits(xmlDocPtr doc, xmlNodePtr node,
|
||||
|
@ -144,6 +144,8 @@ typedef struct ice_config_tag
|
||||
char *master_password;
|
||||
int master_relay_auth;
|
||||
int master_ssl_port;
|
||||
int master_redirect;
|
||||
int max_redirects;
|
||||
|
||||
relay_server *relay;
|
||||
|
||||
@ -158,7 +160,6 @@ typedef struct ice_config_tag
|
||||
char *adminroot_dir;
|
||||
aliases *aliases;
|
||||
unsigned slaves_count;
|
||||
int master_redirect_port;
|
||||
|
||||
char *access_log;
|
||||
char *error_log;
|
||||
|
19
src/client.c
19
src/client.c
@ -119,8 +119,6 @@ void client_destroy(client_t *client)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
if (client->is_slave)
|
||||
slave_host_remove (client);
|
||||
|
||||
if (client->con)
|
||||
connection_close(client->con);
|
||||
@ -171,12 +169,12 @@ int client_read_bytes (client_t *client, void *buf, unsigned len)
|
||||
}
|
||||
|
||||
|
||||
void client_send_302(client_t *client, char *location) {
|
||||
void client_send_302(client_t *client, const char *location) {
|
||||
snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
|
||||
"HTTP/1.0 302 Temporarily Moved\r\n"
|
||||
"Content-Type: text/html\r\n"
|
||||
"Location: %s\r\n\r\n"
|
||||
"<a href=\"%s\">%s</a>", location, location, location);
|
||||
"Moved <a href=\"%s\">here</a>\r\n", location, location);
|
||||
client->respcode = 302;
|
||||
client->refbuf->len = strlen (client->refbuf->data);
|
||||
fserve_add_client (client, NULL);
|
||||
@ -296,16 +294,3 @@ void client_set_queue (client_t *client, refbuf_t *refbuf)
|
||||
refbuf_release (to_release);
|
||||
}
|
||||
|
||||
void client_as_slave (client_t *client)
|
||||
{
|
||||
char *slave_redirect = httpp_getvar (client->parser, "ice-redirect");
|
||||
INFO1 ("client connected as slave from %s", client->con->ip);
|
||||
client->is_slave = 1;
|
||||
if (slave_redirect)
|
||||
{
|
||||
/* this will be something like ip:port */
|
||||
DEBUG1 ("header for auth slave is \"%s\"", slave_redirect);
|
||||
slave_host_add (client, slave_redirect);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,10 +92,9 @@ void client_send_404(client_t *client, char *message);
|
||||
void client_send_401(client_t *client);
|
||||
void client_send_403(client_t *client, const char *reason);
|
||||
void client_send_400(client_t *client, char *message);
|
||||
void client_send_302(client_t *client, char *location);
|
||||
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);
|
||||
void client_set_queue (client_t *client, refbuf_t *refbuf);
|
||||
void client_as_slave (client_t *client);
|
||||
|
||||
#endif /* __CLIENT_H__ */
|
||||
|
@ -1227,7 +1227,7 @@ static void *_handle_connection(void *arg)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
thread_sleep (50000);
|
||||
thread_sleep (100000);
|
||||
}
|
||||
DEBUG0 ("Connection thread done");
|
||||
|
||||
|
10
src/format.c
10
src/format.c
@ -90,8 +90,8 @@ int format_get_plugin (format_type_t type, source_t *source)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
source->format->in_bitrate = rate_setup (10);
|
||||
source->format->out_bitrate = rate_setup (10);
|
||||
source->format->in_bitrate = rate_setup (30);
|
||||
source->format->out_bitrate = rate_setup (30);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -104,8 +104,10 @@ static void find_client_start (source_t *source, client_t *client)
|
||||
{
|
||||
refbuf_t *refbuf = source->burst_point;
|
||||
|
||||
/* we only want to attempt a burst at connection time, not midstream */
|
||||
if (client->intro_offset == -1)
|
||||
/* we only want to attempt a burst at connection time, not midstream
|
||||
* however streams like theora may not have the most recent page marked as
|
||||
* a starting point, so look for one from the burst point */
|
||||
if (client->intro_offset == -1 && source->stream_data_tail->sync_point)
|
||||
refbuf = source->stream_data_tail;
|
||||
else
|
||||
{
|
||||
|
@ -44,9 +44,9 @@ typedef struct ice_global_tag
|
||||
/* relays retrieved from master */
|
||||
struct _relay_server *master_relays;
|
||||
|
||||
/* slave relay list */
|
||||
unsigned int slave_count;
|
||||
struct _slave_host *slaves;
|
||||
/* redirection to slaves */
|
||||
unsigned int redirect_count;
|
||||
struct _redirect_host *redirectors;
|
||||
|
||||
cond_t shutdown_cond;
|
||||
} ice_global_t;
|
||||
|
317
src/slave.c
317
src/slave.c
@ -62,8 +62,9 @@
|
||||
#define CATMODULE "slave"
|
||||
|
||||
static void *_slave_thread(void *arg);
|
||||
static void _add_slave_host (const char *server, int port);
|
||||
static slave_host *find_slave_host (const char *server, int port);
|
||||
static void redirector_add (const char *server, int port, int interval);
|
||||
static redirect_host *find_slave_host (const char *server, int port);
|
||||
static void redirector_clearall (void);
|
||||
|
||||
static thread_type *_slave_thread_id;
|
||||
static int slave_running = 0;
|
||||
@ -140,6 +141,9 @@ void slave_initialize(void)
|
||||
thread_rwlock_create (&slaves_lock);
|
||||
slave_running = 1;
|
||||
max_interval = 0;
|
||||
#ifndef HAVE_CURL
|
||||
WARN0 ("streamlist request disabled, rebuild with libcurl if required");
|
||||
#endif
|
||||
_slave_thread_id = thread_create("Slave Thread", _slave_thread, NULL, THREAD_ATTACHED);
|
||||
}
|
||||
|
||||
@ -155,45 +159,60 @@ void slave_shutdown(void)
|
||||
}
|
||||
|
||||
|
||||
int slave_redirect (const char *mountpoint, client_t *client)
|
||||
int redirect_client (const char *mountpoint, client_t *client)
|
||||
{
|
||||
slave_host *slave = NULL;
|
||||
int ret = 0, which;
|
||||
redirect_host *checking, **trail;
|
||||
|
||||
DEBUG1 ("slave count is %d", global.slave_count);
|
||||
thread_rwlock_rlock (&slaves_lock);
|
||||
/* select slave entry */
|
||||
if (global.slave_count)
|
||||
if (global.redirect_count == 0)
|
||||
{
|
||||
int which=(int) (((float)global.slave_count)*rand()/(RAND_MAX+1.0));
|
||||
slave = global.slaves;
|
||||
while (slave && which)
|
||||
{
|
||||
slave = slave->next;
|
||||
which--;
|
||||
}
|
||||
DEBUG2 ("selected %s:%d", slave->server,slave->port);
|
||||
thread_rwlock_unlock (&slaves_lock);
|
||||
return 0;
|
||||
}
|
||||
if (slave)
|
||||
{
|
||||
char *location = NULL;
|
||||
/* add 13 for "http://" the port ':' and nul */
|
||||
int len = strlen(mountpoint) + strlen (slave->server) + 13;
|
||||
which=(int) (((float)global.redirect_count)*rand()/(RAND_MAX+1.0)) + 1;
|
||||
checking = global.redirectors;
|
||||
trail = &global.redirectors;
|
||||
|
||||
location = malloc (len);
|
||||
if (location)
|
||||
DEBUG2 ("random selection %d (out of %d)", which, global.redirect_count);
|
||||
while (checking)
|
||||
{
|
||||
DEBUG2 ("...%s:%d", checking->server, checking->port);
|
||||
if (checking->next_update && checking->next_update+10 < global.time)
|
||||
{
|
||||
/* no streamist request, expire slave for now */
|
||||
*trail = checking->next;
|
||||
global.redirect_count--;
|
||||
/* free slave details */
|
||||
INFO2 ("dropping redirector for %s:%d", checking->server, checking->port);
|
||||
free (checking->server);
|
||||
free (checking);
|
||||
checking = *trail;
|
||||
if (which > 0)
|
||||
which--; /* we are 1 less now */
|
||||
continue;
|
||||
}
|
||||
if (--which == 0)
|
||||
{
|
||||
char *location;
|
||||
/* add enough for "http://" the port ':' and nul */
|
||||
int len = strlen (mountpoint) + strlen (checking->server) + 13;
|
||||
|
||||
INFO2 ("redirecting client to slave server "
|
||||
"at %s:%d", slave->server, slave->port);
|
||||
snprintf (location, len, "http://%s:%d%s", slave->server,
|
||||
slave->port, mountpoint);
|
||||
thread_rwlock_unlock (&slaves_lock);
|
||||
"at %s:%d", checking->server, checking->port);
|
||||
location = malloc (len);
|
||||
snprintf (location, len, "http://%s:%d%s", checking->server,
|
||||
checking->port, mountpoint);
|
||||
client_send_302 (client, location);
|
||||
free (location);
|
||||
return 1;
|
||||
ret = 1;
|
||||
}
|
||||
trail = &checking->next;
|
||||
checking = checking->next;
|
||||
}
|
||||
thread_rwlock_unlock (&slaves_lock);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -214,7 +233,7 @@ static void *start_relay_stream (void *arg)
|
||||
do
|
||||
{
|
||||
char *auth_header;
|
||||
char *redirect_header = NULL, *server_id;
|
||||
char *server_id;
|
||||
ice_config_t *config;
|
||||
|
||||
streamsock = sock_connect_wto (relay->server, relay->port, 10);
|
||||
@ -242,22 +261,10 @@ static void *start_relay_stream (void *arg)
|
||||
snprintf (auth_header, len,
|
||||
"Authorization: Basic %s\r\n", esc_authorisation);
|
||||
free(esc_authorisation);
|
||||
|
||||
/* header to use for participating in load sharing */
|
||||
if (config->master_redirect_port)
|
||||
{
|
||||
len = strlen ("ice-redirect:") + strlen (config->hostname) + 10;
|
||||
redirect_header = malloc (len);
|
||||
snprintf (redirect_header, len, "ice-redirect: %s:%d\r\n",
|
||||
config->hostname, config->master_redirect_port);
|
||||
}
|
||||
else
|
||||
redirect_header = strdup ("");
|
||||
}
|
||||
else
|
||||
{
|
||||
auth_header = strdup ("");
|
||||
redirect_header = strdup ("");
|
||||
}
|
||||
config_release_config ();
|
||||
|
||||
@ -270,16 +277,13 @@ static void *start_relay_stream (void *arg)
|
||||
"User-Agent: %s\r\n"
|
||||
"%s"
|
||||
"%s"
|
||||
"%s"
|
||||
"\r\n",
|
||||
relay->mount,
|
||||
server_id,
|
||||
relay->mp3metadata?"Icy-MetaData: 1\r\n":"",
|
||||
redirect_header,
|
||||
auth_header);
|
||||
free (server_id);
|
||||
free (auth_header);
|
||||
free (redirect_header);
|
||||
memset (header, 0, sizeof(header));
|
||||
if (util_read_header (con->sock, header, 4096, READ_ENTIRE_HEADER) == 0)
|
||||
{
|
||||
@ -380,7 +384,10 @@ static void check_relay_stream (relay_server *relay)
|
||||
/* new relay, reserve the name */
|
||||
relay->source = source_reserve (relay->localmount);
|
||||
if (relay->source)
|
||||
{
|
||||
DEBUG1("Adding relay source at mountpoint \"%s\"", relay->localmount);
|
||||
relay->cleanup = 1;
|
||||
}
|
||||
else
|
||||
WARN1 ("new relay but source \"%s\" already exists", relay->localmount);
|
||||
}
|
||||
@ -395,16 +402,8 @@ static void check_relay_stream (relay_server *relay)
|
||||
stats_event (relay->localmount, NULL, NULL);
|
||||
break;
|
||||
}
|
||||
if (relay->on_demand)
|
||||
if (relay->on_demand && source->on_demand_req == 0)
|
||||
{
|
||||
ice_config_t *config = config_get_config ();
|
||||
mount_proxy *mountinfo = config_find_mount (config, relay->localmount);
|
||||
|
||||
if (mountinfo == NULL)
|
||||
source_update_settings (config, relay->source, mountinfo);
|
||||
config_release_config ();
|
||||
slave_rebuild_mounts();
|
||||
stats_event (relay->localmount, "listeners", "0");
|
||||
relay->source->on_demand = relay->on_demand;
|
||||
|
||||
if (source->fallback_mount && source->fallback_override)
|
||||
@ -431,11 +430,14 @@ static void check_relay_stream (relay_server *relay)
|
||||
|
||||
} while (0);
|
||||
/* the relay thread may of shut down itself */
|
||||
if (relay->cleanup && relay->thread)
|
||||
if (relay->cleanup)
|
||||
{
|
||||
DEBUG1 ("waiting for relay thread for \"%s\"", relay->localmount);
|
||||
thread_join (relay->thread);
|
||||
relay->thread = NULL;
|
||||
if (relay->thread)
|
||||
{
|
||||
DEBUG1 ("waiting for relay thread for \"%s\"", relay->localmount);
|
||||
thread_join (relay->thread);
|
||||
relay->thread = NULL;
|
||||
}
|
||||
relay->cleanup = 0;
|
||||
relay->running = 0;
|
||||
|
||||
@ -541,7 +543,8 @@ update_relays (relay_server **relay_list, relay_server *new_relay_list)
|
||||
}
|
||||
|
||||
|
||||
static void relay_check_streams (relay_server *to_start, relay_server *to_free, int skip_timer)
|
||||
static void relay_check_streams (relay_server *to_start,
|
||||
relay_server *to_free, int skip_timer)
|
||||
{
|
||||
relay_server *relay;
|
||||
|
||||
@ -588,6 +591,7 @@ struct master_conn_details
|
||||
char *username;
|
||||
char *password;
|
||||
char *server_id;
|
||||
char *args;
|
||||
relay_server *new_relays;
|
||||
};
|
||||
|
||||
@ -701,7 +705,7 @@ static void *streamlist_thread (void *arg)
|
||||
const char *protocol = "http";
|
||||
int port = master->port;
|
||||
char error [CURL_ERROR_SIZE];
|
||||
char url [300], auth [100];
|
||||
char url [1024], auth [100];
|
||||
|
||||
if (master->ssl_port)
|
||||
{
|
||||
@ -709,8 +713,8 @@ static void *streamlist_thread (void *arg)
|
||||
port = master->ssl_port;
|
||||
}
|
||||
snprintf (auth, sizeof (auth), "%s:%s", master->username, master->password);
|
||||
snprintf (url, sizeof (url), "%s://%s:%d/admin/streamlist.txt",
|
||||
protocol, master->server, port);
|
||||
snprintf (url, sizeof (url), "%s://%s:%d/admin/streamlist.txt%s",
|
||||
protocol, master->server, port, master->args);
|
||||
handle = curl_easy_init ();
|
||||
curl_easy_setopt (handle, CURLOPT_USERAGENT, master->server_id);
|
||||
curl_easy_setopt (handle, CURLOPT_URL, url);
|
||||
@ -746,6 +750,7 @@ static void *streamlist_thread (void *arg)
|
||||
free (master->password);
|
||||
free (master->buffer);
|
||||
free (master->server_id);
|
||||
free (master->args);
|
||||
free (master);
|
||||
return NULL;
|
||||
}
|
||||
@ -769,24 +774,39 @@ static void update_from_master (ice_config_t *config)
|
||||
details->send_auth = config->master_relay_auth;
|
||||
details->on_demand = config->on_demand;
|
||||
details->server_id = strdup (config->server_id);
|
||||
if (config->master_redirect)
|
||||
{
|
||||
details->args = malloc (4096);
|
||||
snprintf (details->args, 4096, "?rserver=%s&rport=%d&interval=%d",
|
||||
config->hostname, config->port, config->master_update_interval);
|
||||
}
|
||||
else
|
||||
details->args = strdup ("");
|
||||
|
||||
thread_create ("streamlist", streamlist_thread, details, THREAD_DETACHED);
|
||||
#else
|
||||
WARN0 ("streamlist request disabled, rebuild with libcurl if required");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void update_master_as_slave (ice_config_t *config)
|
||||
{
|
||||
if (config->master_server == NULL || config->master_redirect_port == 0)
|
||||
redirect_host *redirect;
|
||||
|
||||
if (config->master_server == NULL || config->master_redirect == 0 || config->max_redirects == 0)
|
||||
{
|
||||
redirector_clearall();
|
||||
return;
|
||||
}
|
||||
|
||||
thread_rwlock_wlock (&slaves_lock);
|
||||
DEBUG1 ("redirect port is %d", config->master_redirect_port);
|
||||
if (find_slave_host (config->master_server,
|
||||
config->master_server_port) == NULL)
|
||||
_add_slave_host (config->master_server, config->master_server_port);
|
||||
redirect = find_slave_host (config->master_server, config->master_server_port);
|
||||
if (redirect == NULL)
|
||||
{
|
||||
INFO2 ("adding master %s:%d", config->master_server, config->master_server_port);
|
||||
redirector_add (config->master_server, config->master_server_port, 0);
|
||||
}
|
||||
else
|
||||
redirect->next_update += max_interval;
|
||||
thread_rwlock_unlock (&slaves_lock);
|
||||
}
|
||||
|
||||
@ -852,6 +872,7 @@ static void *_slave_thread(void *arg)
|
||||
INFO0 ("shutting down current relays");
|
||||
relay_check_streams (NULL, global.relays, 0);
|
||||
relay_check_streams (NULL, global.master_relays, 0);
|
||||
redirector_clearall();
|
||||
|
||||
INFO0 ("Slave thread shutdown complete");
|
||||
|
||||
@ -871,108 +892,100 @@ relay_server *slave_find_relay (relay_server *relays, const char *mount)
|
||||
}
|
||||
|
||||
|
||||
/* remove this slave clients entry in the slave host list */
|
||||
void slave_host_remove (client_t *client)
|
||||
/* drop all redirection details.
|
||||
*/
|
||||
static void redirector_clearall (void)
|
||||
{
|
||||
const char *var = httpp_getvar (client->parser, "ice-redirect");
|
||||
|
||||
if (var)
|
||||
thread_rwlock_wlock (&slaves_lock);
|
||||
while (global.redirectors)
|
||||
{
|
||||
slave_host *slave, **trail;
|
||||
char *server = strdup (var), *separator;
|
||||
int port;
|
||||
|
||||
separator = strchr (server, ':');
|
||||
if (separator == NULL)
|
||||
{
|
||||
free (server);
|
||||
return;
|
||||
}
|
||||
*separator = '\0';
|
||||
port = atoi (separator+1);
|
||||
thread_rwlock_wlock (&slaves_lock);
|
||||
slave = global.slaves;
|
||||
trail = &global.slaves;
|
||||
while (slave)
|
||||
{
|
||||
if (strcmp (slave->server, server) == 0 && slave->port == port)
|
||||
{
|
||||
slave->count--;
|
||||
if (slave->count == 0)
|
||||
{
|
||||
INFO2 ("slave at %s:%d removed", slave->server, slave->port);
|
||||
*trail = slave->next;
|
||||
free (slave->server);
|
||||
global.slave_count--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
trail = &slave->next;
|
||||
slave = slave->next;
|
||||
}
|
||||
thread_rwlock_unlock (&slaves_lock);
|
||||
redirect_host *current = global.redirectors;
|
||||
global.redirectors = current->next;
|
||||
free (current->server);
|
||||
free (current);
|
||||
}
|
||||
global.redirect_count = 0;
|
||||
thread_rwlock_unlock (&slaves_lock);
|
||||
}
|
||||
|
||||
|
||||
/* with the provided header (eg "localhost:8000") add a new slave host
|
||||
* entry to so that clients can redirect to other sites when full
|
||||
/* Add new redirectors or update any existing ones
|
||||
*/
|
||||
void slave_host_add (client_t *client, const char *header)
|
||||
void redirector_update (client_t *client)
|
||||
{
|
||||
slave_host *slave;
|
||||
char *server, *separator;
|
||||
int port;
|
||||
redirect_host *redirect;
|
||||
const char *rserver = httpp_get_query_param (client->parser, "rserver");
|
||||
char *value;
|
||||
int rport, interval;
|
||||
|
||||
if (rserver==NULL) return;
|
||||
value = httpp_get_query_param (client->parser, "rport");
|
||||
if (value == NULL) return;
|
||||
rport = atoi (value);
|
||||
if (rport <= 0) return;
|
||||
value = httpp_get_query_param (client->parser, "interval");
|
||||
if (value == NULL) return;
|
||||
interval = atoi (value);
|
||||
if (interval < 5) return;
|
||||
|
||||
if (client == NULL || header == NULL)
|
||||
return;
|
||||
|
||||
server = strdup (header);
|
||||
separator = strchr (server, ':');
|
||||
if (separator == NULL)
|
||||
{
|
||||
free (server);
|
||||
return;
|
||||
}
|
||||
*separator = '\0';
|
||||
port = atoi (separator+1);
|
||||
thread_rwlock_wlock (&slaves_lock);
|
||||
slave = find_slave_host (server, port);
|
||||
if (slave)
|
||||
redirect = find_slave_host (rserver, rport);
|
||||
if (redirect == NULL)
|
||||
{
|
||||
slave->count++;
|
||||
DEBUG0 ("already exists, increasing count");
|
||||
redirector_add (rserver, rport, interval);
|
||||
}
|
||||
else
|
||||
_add_slave_host (server, port);
|
||||
thread_rwlock_unlock (&slaves_lock);
|
||||
free (server);
|
||||
}
|
||||
|
||||
static slave_host *find_slave_host (const char *server, int port)
|
||||
{
|
||||
slave_host *slave = global.slaves;
|
||||
while (slave)
|
||||
{
|
||||
if (strcmp (slave->server, server) == 0 && slave->port == port)
|
||||
break;
|
||||
slave = slave->next;
|
||||
DEBUG2 ("touch update on %s:%d", redirect->server, redirect->port);
|
||||
redirect->next_update = global.time + interval;
|
||||
}
|
||||
return slave;
|
||||
thread_rwlock_unlock (&slaves_lock);
|
||||
}
|
||||
|
||||
static void _add_slave_host (const char *server, int port)
|
||||
|
||||
|
||||
/* search list of redirectors for a matching entry, lock must be held before
|
||||
* invoking this function
|
||||
*/
|
||||
static redirect_host *find_slave_host (const char *server, int port)
|
||||
{
|
||||
slave_host *slave = calloc (1, sizeof (slave_host));
|
||||
if (slave == NULL)
|
||||
return;
|
||||
slave->server = strdup (server);
|
||||
slave->port = port;
|
||||
slave->count = 1;
|
||||
slave->next = global.slaves;
|
||||
global.slaves = slave;
|
||||
global.slave_count++;
|
||||
INFO3 ("slave (%d) at %s:%d added", global.slave_count,
|
||||
slave->server, slave->port);
|
||||
redirect_host *redirect = global.redirectors;
|
||||
while (redirect)
|
||||
{
|
||||
if (strcmp (redirect->server, server) == 0 && redirect->port == port)
|
||||
break;
|
||||
redirect = redirect->next;
|
||||
}
|
||||
return redirect;
|
||||
}
|
||||
|
||||
|
||||
static void redirector_add (const char *server, int port, int interval)
|
||||
{
|
||||
ice_config_t *config = config_get_config();
|
||||
int allowed = config->max_redirects;
|
||||
redirect_host *redirect;
|
||||
|
||||
config_release_config();
|
||||
|
||||
if (global.redirect_count >= allowed)
|
||||
{
|
||||
INFO1 ("redirect to slave limit reached (%d)", global.redirect_count);
|
||||
return;
|
||||
}
|
||||
redirect = calloc (1, sizeof (redirect_host));
|
||||
if (redirect == NULL)
|
||||
abort();
|
||||
redirect->server = strdup (server);
|
||||
redirect->port = port;
|
||||
if (interval == 0)
|
||||
redirect->next_update = (time_t)0;
|
||||
else
|
||||
redirect->next_update = global.time + interval;
|
||||
redirect->next = global.redirectors;
|
||||
global.redirectors = redirect;
|
||||
global.redirect_count++;
|
||||
INFO3 ("slave (%d) at %s:%d added", global.redirect_count,
|
||||
redirect->server, redirect->port);
|
||||
}
|
||||
|
||||
|
13
src/slave.h
13
src/slave.h
@ -35,22 +35,21 @@ typedef struct _relay_server {
|
||||
struct _relay_server *next;
|
||||
} relay_server;
|
||||
|
||||
typedef struct _slave_host
|
||||
typedef struct _redirect_host
|
||||
{
|
||||
char *server;
|
||||
int port;
|
||||
unsigned int count;
|
||||
struct _slave_host *next;
|
||||
} slave_host;
|
||||
time_t next_update;
|
||||
struct _redirect_host *next;
|
||||
} redirect_host;
|
||||
|
||||
void slave_initialize(void);
|
||||
void slave_shutdown(void);
|
||||
void slave_recheck_mounts (void);
|
||||
void slave_rebuild_mounts (void);
|
||||
relay_server *slave_find_relay (relay_server *relays, const char *mount);
|
||||
int slave_redirect (const char *mountpoint, struct _client_tag *client);
|
||||
void slave_host_add (struct _client_tag *client, const char *header);
|
||||
void slave_host_remove (struct _client_tag *client);
|
||||
int redirect_client (const char *mountpoint, struct _client_tag *client);
|
||||
void redirector_update (struct _client_tag *client);
|
||||
relay_server *relay_free (relay_server *relay);
|
||||
|
||||
#endif /* __SLAVE_H__ */
|
||||
|
@ -436,16 +436,18 @@ static void get_next_buffer (source_t *source)
|
||||
/* take the lock */
|
||||
thread_mutex_lock (&source->lock);
|
||||
|
||||
if (current >= source->client_stats_update)
|
||||
if (source->client && current >= source->client_stats_update)
|
||||
{
|
||||
stats_event_args (source->mount, "outgoing_bitrate", "%ld",
|
||||
8 * rate_avg (source->format->out_bitrate));
|
||||
(8 * rate_avg (source->format->out_bitrate))/1000);
|
||||
stats_event_args (source->mount, "incoming_bitrate", "%ld",
|
||||
8 * rate_avg (source->format->in_bitrate));
|
||||
(8 * rate_avg (source->format->in_bitrate))/1000);
|
||||
stats_event_args (source->mount, "total_bytes_read",
|
||||
FORMAT_UINT64, source->format->read_bytes);
|
||||
stats_event_args (source->mount, "total_bytes_sent",
|
||||
FORMAT_UINT64, source->format->sent_bytes);
|
||||
stats_event_args (source->mount, "connected", FORMAT_UINT64,
|
||||
(uint64_t)(current - source->client->con->con_time));
|
||||
source->client_stats_update = current + 5;
|
||||
}
|
||||
if (fds < 0)
|
||||
|
11
src/yp.c
11
src/yp.c
@ -91,6 +91,7 @@ static int yp_running;
|
||||
static time_t now;
|
||||
static thread_type *yp_thread;
|
||||
static volatile unsigned client_limit = 0;
|
||||
static volatile char *server_version = NULL;
|
||||
|
||||
static void *yp_update_thread(void *arg);
|
||||
static void add_yp_info (ypdata_t *yp, void *info, int type);
|
||||
@ -217,6 +218,8 @@ void yp_recheck_config (ice_config_t *config)
|
||||
server = server->next;
|
||||
}
|
||||
client_limit = config->client_limit;
|
||||
free (server_version);
|
||||
server_version = strdup (config->server_id);
|
||||
/* for each yp url in config, check to see if one exists
|
||||
if not, then add it. */
|
||||
for (i=0 ; i < config->num_yp_directories; i++)
|
||||
@ -242,7 +245,7 @@ void yp_recheck_config (ice_config_t *config)
|
||||
}
|
||||
if (server->touch_interval < 30)
|
||||
server->touch_interval = 30;
|
||||
curl_easy_setopt (server->curl, CURLOPT_USERAGENT, ICECAST_VERSION_STRING);
|
||||
curl_easy_setopt (server->curl, CURLOPT_USERAGENT, server_version);
|
||||
curl_easy_setopt (server->curl, CURLOPT_URL, server->url);
|
||||
curl_easy_setopt (server->curl, CURLOPT_HEADERFUNCTION, handle_returned_header);
|
||||
curl_easy_setopt (server->curl, CURLOPT_WRITEFUNCTION, handle_returned_data);
|
||||
@ -354,6 +357,8 @@ static unsigned do_yp_add (ypdata_t *yp, char *s, unsigned len)
|
||||
free (value);
|
||||
|
||||
value = stats_get_value (yp->mount, "bitrate");
|
||||
if (value == NULL)
|
||||
value = stats_get_value (yp->mount, "incoming_bitrate");
|
||||
add_yp_info (yp, value, YP_BITRATE);
|
||||
free (value);
|
||||
|
||||
@ -845,7 +850,7 @@ void yp_add (const char *mount)
|
||||
yp->server = server;
|
||||
yp->touch_interval = server->touch_interval;
|
||||
yp->next = server->pending_mounts;
|
||||
yp->next_update = time(NULL) + 5;
|
||||
yp->next_update = global.time + 60;
|
||||
server->pending_mounts = yp;
|
||||
yp_update = 1;
|
||||
}
|
||||
@ -925,6 +930,8 @@ void yp_shutdown (void)
|
||||
if (yp_thread)
|
||||
thread_join (yp_thread);
|
||||
curl_global_cleanup();
|
||||
free (server_version);
|
||||
server_version = NULL;
|
||||
INFO0 ("YP thread down");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user