1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-12-04 14:46:30 -05:00

merge in fallback to file, override also works

svn path=/icecast/trunk/icecast/; revision=9434
This commit is contained in:
Karl Heyes 2005-06-10 15:42:06 +00:00
parent 05a14555d9
commit be78a3ae11
6 changed files with 137 additions and 26 deletions

View File

@ -434,6 +434,17 @@ mountpoint that is just not available, then those clients will be disconnected.
If clients are falling back to a mountpoint and the fallback-mount is not actively streaming If clients are falling back to a mountpoint and the fallback-mount is not actively streaming
but defines a fallback-mount itself then those clients may be moved there instead. but defines a fallback-mount itself then those clients may be moved there instead.
This multi-level fallback allows clients to cascade several mountpoints. This multi-level fallback allows clients to cascade several mountpoints.
<p>A fallback mount can also state a file that is located in webroot. This is useful for
playing a pre-recorded file in the case of a stream going down. It will repeat until either
the listener disconnects or a stream comes back available and takes the listeners back.
As per usual, the file format should match the stream format, failing to do so may cause
problems with playback.
</p>
<p>Note that the fallback file is not timed so be careful if you intend to relay this.
They are fine on slave streams but don't use them on master streams, if you do then the
relay will consume stream data at a faster rate and the listeners on the relay would
eventually get kicked off.
</p>
</div> </div>
<h4>fallback-override</h4> <h4>fallback-override</h4>
<div class="indentedbox"> <div class="indentedbox">

View File

@ -75,10 +75,11 @@ void client_destroy(client_t *client)
/* write log entry if ip is set (some things don't set it, like outgoing /* write log entry if ip is set (some things don't set it, like outgoing
* slave requests * slave requests
*/ */
if(client->con->ip) if (client->con && client->con->ip)
logging_access(client); logging_access(client);
connection_close(client->con); if (client->con)
connection_close(client->con);
httpp_destroy(client->parser); httpp_destroy(client->parser);
global_lock (); global_lock ();

View File

@ -150,8 +150,16 @@ int format_check_file_buffer (source_t *source, client_t *client)
if (refbuf == NULL) if (refbuf == NULL)
{ {
/* client refers to no data, must be from a move */ /* client refers to no data, must be from a move */
find_client_start (source, client); if (source->client->con)
return -1; {
find_client_start (source, client);
return -1;
}
/* source -> file fallback, need a refbuf for data */
refbuf = refbuf_new (4096);
client->refbuf = refbuf;
client->pos = refbuf->len;
client->intro_offset = 0;
} }
if (client->pos == refbuf->len) if (client->pos == refbuf->len)
{ {

View File

@ -317,7 +317,7 @@ static void *fserv_thread_function(void *arg)
return NULL; return NULL;
} }
static const char *fserve_content_type(const char *path) char *fserve_content_type (const char *path)
{ {
char *ext = util_get_extension(path); char *ext = util_get_extension(path);
mime_type exttype = {ext, NULL}; mime_type exttype = {ext, NULL};

View File

@ -32,6 +32,7 @@ typedef struct _fserve_t
void fserve_initialize(void); void fserve_initialize(void);
void fserve_shutdown(void); void fserve_shutdown(void);
int fserve_client_create(client_t *httpclient, const char *path); int fserve_client_create(client_t *httpclient, const char *path);
char *fserve_content_type (const char *path);
#endif #endif

View File

@ -48,6 +48,7 @@
#include "util.h" #include "util.h"
#include "source.h" #include "source.h"
#include "format.h" #include "format.h"
#include "fserve.h"
#include "auth.h" #include "auth.h"
#include "os.h" #include "os.h"
@ -373,6 +374,8 @@ void source_move_clients (source_t *source, source_t *dest)
{ {
client_set_queue (client, NULL); client_set_queue (client, NULL);
client->check_buffer = format_check_file_buffer; client->check_buffer = format_check_file_buffer;
if (source->con == NULL)
client->intro_offset = -1;
} }
avl_insert (dest->pending_tree, (void *)client); avl_insert (dest->pending_tree, (void *)client);
@ -397,6 +400,8 @@ void source_move_clients (source_t *source, source_t *dest)
{ {
client_set_queue (client, NULL); client_set_queue (client, NULL);
client->check_buffer = format_check_file_buffer; client->check_buffer = format_check_file_buffer;
if (source->con == NULL)
client->intro_offset = -1;
} }
avl_insert (dest->pending_tree, (void *)client); avl_insert (dest->pending_tree, (void *)client);
count++; count++;
@ -435,10 +440,16 @@ static refbuf_t *get_next_buffer (source_t *source)
delay = 0; delay = 0;
while (global.running == ICE_RUNNING && source->running) while (global.running == ICE_RUNNING && source->running)
{ {
int fds; int fds = 0;
time_t current = time (NULL); time_t current = time (NULL);
fds = util_timed_wait_for_fd (source->con->sock, delay); if (source->client->con)
fds = util_timed_wait_for_fd (source->con->sock, delay);
else
{
thread_sleep (delay*1000);
source->last_read = current;
}
if (current >= source->client_stats_update) if (current >= source->client_stats_update)
{ {
@ -470,7 +481,7 @@ static refbuf_t *get_next_buffer (source_t *source)
} }
source->last_read = current; source->last_read = current;
refbuf = source->format->get_buffer (source); refbuf = source->format->get_buffer (source);
if (source->client->con->error) if (source->client->con && source->client->con->error)
{ {
INFO1 ("End of Stream %s", source->mount); INFO1 ("End of Stream %s", source->mount);
source->running = 0; source->running = 0;
@ -585,7 +596,8 @@ static void source_init (source_t *source)
stats_event_inc (NULL, "source_total_connections"); stats_event_inc (NULL, "source_total_connections");
stats_event (source->mount, "slow_listeners", "0"); stats_event (source->mount, "slow_listeners", "0");
sock_set_blocking (source->con->sock, SOCK_NONBLOCK); if (source->client->con)
sock_set_blocking (source->con->sock, SOCK_NONBLOCK);
DEBUG0("Source creation complete"); DEBUG0("Source creation complete");
source->last_read = time (NULL); source->last_read = time (NULL);
@ -1095,6 +1107,9 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
*/ */
void source_update_settings (ice_config_t *config, source_t *source, mount_proxy *mountinfo) void source_update_settings (ice_config_t *config, source_t *source, mount_proxy *mountinfo)
{ {
/* skip if source is a fallback to file */
if (source->running && source->client->con == NULL)
return;
/* set global settings first */ /* set global settings first */
source->queue_size_limit = config->queue_size_limit; source->queue_size_limit = config->queue_size_limit;
source->timeout = config->source_timeout; source->timeout = config->source_timeout;
@ -1147,26 +1162,29 @@ void source_update_settings (ice_config_t *config, source_t *source, mount_proxy
void *source_client_thread (void *arg) void *source_client_thread (void *arg)
{ {
source_t *source = arg; source_t *source = arg;
const char ok_msg[] = "HTTP/1.0 200 OK\r\n\r\n";
int bytes;
const char *agent;
source->client->respcode = 200; if (source->client && source->client->con)
bytes = sock_write_bytes (source->client->con->sock, ok_msg, sizeof (ok_msg)-1);
if (bytes < (int)(sizeof (ok_msg)-1))
{ {
global_lock(); const char ok_msg[] = "HTTP/1.0 200 OK\r\n\r\n";
global.sources--; int bytes;
global_unlock(); const char *agent;
WARN0 ("Error writing 200 OK message to source client");
source_free_source (source);
return NULL;
}
stats_event (source->mount, "source_ip", source->client->con->ip);
agent = httpp_getvar (source->client->parser, "user-agent");
if (agent)
stats_event (source->mount, "user_agent", agent);
source->client->respcode = 200;
bytes = sock_write_bytes (source->client->con->sock, ok_msg, sizeof (ok_msg)-1);
if (bytes < (int)(sizeof (ok_msg)-1))
{
global_lock();
global.sources--;
global_unlock();
WARN0 ("Error writing 200 OK message to source client");
source_free_source (source);
return NULL;
}
stats_event (source->mount, "source_ip", source->client->con->ip);
agent = httpp_getvar (source->client->parser, "user-agent");
if (agent)
stats_event (source->mount, "user_agent", agent);
}
stats_event_inc(NULL, "source_client_connections"); stats_event_inc(NULL, "source_client_connections");
stats_event (source->mount, "listeners", "0"); stats_event (source->mount, "listeners", "0");
@ -1214,6 +1232,67 @@ static void source_run_script (char *command, char *mountpoint)
#endif #endif
static void *source_fallback_file (void *arg)
{
char *mount = arg;
char *type;
char *path;
unsigned int len;
FILE *file = NULL;
source_t *source = NULL;
ice_config_t *config;
http_parser_t *parser;
do
{
if (mount == NULL || mount[0] != '/')
break;
config = config_get_config();
len = strlen (config->webroot_dir) + strlen (mount) + 1;
path = malloc (len);
if (path)
snprintf (path, len, "%s%s", config->webroot_dir, mount);
config_release_config ();
if (path == NULL)
break;
file = fopen (path, "rb");
if (file == NULL)
{
DEBUG1 ("unable to open file \"%s\"", path);
free (path);
break;
}
free (path);
source = source_reserve (mount);
if (source == NULL)
{
DEBUG1 ("mountpoint \"%s\" already reserved", mount);
break;
}
type = fserve_content_type (mount);
parser = httpp_create_parser();
httpp_initialize (parser, NULL);
httpp_setvar (parser, "content-type", type);
source->hidden = 1;
source->yp_public = 0;
source->intro_file = file;
source->parser = parser;
file = NULL;
if (connection_complete_source (source) < 0)
break;
source_client_thread (source);
} while (0);
if (file)
fclose (file);
free (mount);
return NULL;
}
/* rescan the mount list, so that xsl files are updated to show /* rescan the mount list, so that xsl files are updated to show
* unconnected but active fallback mountpoints * unconnected but active fallback mountpoints
*/ */
@ -1249,6 +1328,17 @@ void source_recheck_mounts (void)
else else
stats_event (mount->mountname, NULL, NULL); stats_event (mount->mountname, NULL, NULL);
/* check for fallback to file */
if (global.running == ICE_RUNNING && mount->fallback_mount)
{
source_t *fallback = source_find_mount (mount->fallback_mount);
if (fallback == NULL)
{
thread_create ("Fallback file thread", source_fallback_file,
strdup (mount->fallback_mount), THREAD_DETACHED);
}
}
mount = mount->next; mount = mount->next;
} }
avl_tree_unlock (global.source_tree); avl_tree_unlock (global.source_tree);