Commit c359faf1 authored by Michael Smith's avatar Michael Smith

More features:

  -- per mountpoint listener maxima
  -- static configuration of mountpoint fallbacks
  -- stream dumping (write incoming stream to disk)

Fixed some warnings that other people introduced.

svn path=/trunk/icecast/; revision=4383
parent d2fbef60
...@@ -69,6 +69,17 @@ void client_send_404(client_t *client, char *message) { ...@@ -69,6 +69,17 @@ void client_send_404(client_t *client, char *message) {
client_destroy(client); client_destroy(client);
} }
void client_send_504(client_t *client, char *message) {
int bytes;
client->respcode = 504;
bytes = sock_write(client->con->sock,
"HTTP/1.0 504 Server Full\r\n"
"Content-Type: text/html\r\n\r\n"
"<b>%s</b>\r\n", message);
if (bytes > 0) client->con->sent_bytes = bytes;
client_destroy(client);
}
void client_send_401(client_t *client) { void client_send_401(client_t *client) {
int bytes = sock_write(client->con->sock, int bytes = sock_write(client->con->sock,
"HTTP/1.0 401 Authentication Required\r\n" "HTTP/1.0 401 Authentication Required\r\n"
......
...@@ -29,6 +29,7 @@ typedef struct _client_tag ...@@ -29,6 +29,7 @@ typedef struct _client_tag
client_t *client_create(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_destroy(client_t *client);
void client_send_504(client_t *client, char *message);
void client_send_404(client_t *client, char *message); void client_send_404(client_t *client, char *message);
void client_send_401(client_t *client); void client_send_401(client_t *client);
void client_send_400(client_t *client, char *message); void client_send_400(client_t *client, char *message);
......
...@@ -296,6 +296,7 @@ static connection_t *_get_connection(void) ...@@ -296,6 +296,7 @@ static connection_t *_get_connection(void)
int connection_create_source(client_t *client, connection_t *con, http_parser_t *parser, char *mount) { int connection_create_source(client_t *client, connection_t *con, http_parser_t *parser, char *mount) {
source_t *source; source_t *source;
char *contenttype; char *contenttype;
mount_proxy *mountproxy, *mountinfo = NULL;
/* check to make sure this source wouldn't /* check to make sure this source wouldn't
** be over the limit ** be over the limit
...@@ -311,6 +312,15 @@ int connection_create_source(client_t *client, connection_t *con, http_parser_t ...@@ -311,6 +312,15 @@ int connection_create_source(client_t *client, connection_t *con, http_parser_t
stats_event_inc(NULL, "sources"); stats_event_inc(NULL, "sources");
mountproxy = config_get_config()->mounts;
while(mountproxy) {
if(!strcmp(mountproxy->mountname, mount)) {
mountinfo = mountproxy;
break;
}
mountproxy = mountproxy->next;
}
contenttype = httpp_getvar(parser, "content-type"); contenttype = httpp_getvar(parser, "content-type");
if (contenttype != NULL) { if (contenttype != NULL) {
...@@ -319,12 +329,13 @@ int connection_create_source(client_t *client, connection_t *con, http_parser_t ...@@ -319,12 +329,13 @@ int connection_create_source(client_t *client, connection_t *con, http_parser_t
WARN1("Content-type \"%s\" not supported, dropping source", contenttype); WARN1("Content-type \"%s\" not supported, dropping source", contenttype);
goto fail; goto fail;
} else { } else {
source = source_create(client, con, parser, mount, format); source = source_create(client, con, parser, mount,
format, mountinfo);
} }
} else { } else {
format_type_t format = FORMAT_TYPE_MP3; format_type_t format = FORMAT_TYPE_MP3;
ERROR0("No content-type header, falling back to backwards compatibility mode for icecast 1.x relays. Assuming content is mp3."); ERROR0("No content-type header, falling back to backwards compatibility mode for icecast 1.x relays. Assuming content is mp3.");
source = source_create(client, con, parser, mount, format); source = source_create(client, con, parser, mount, format, mountinfo);
} }
source->send_return = 1; source->send_return = 1;
...@@ -762,13 +773,8 @@ static void _handle_get_request(connection_t *con, ...@@ -762,13 +773,8 @@ static void _handle_get_request(connection_t *con,
global_lock(); global_lock();
if (global.clients >= config_get_config()->client_limit) { if (global.clients >= config_get_config()->client_limit) {
client->respcode = 504; client_send_504(client,
bytes = sock_write(client->con->sock, "The server is already full. Try again later.");
"HTTP/1.0 504 Server Full\r\n"
"Content-Type: text/html\r\n\r\n"
"<b>The server is already full. Try again later.</b>\r\n");
if (bytes > 0) client->con->sent_bytes = bytes;
client_destroy(client);
global_unlock(); global_unlock();
return; return;
} }
...@@ -781,18 +787,23 @@ static void _handle_get_request(connection_t *con, ...@@ -781,18 +787,23 @@ static void _handle_get_request(connection_t *con,
global_lock(); global_lock();
if (global.clients >= config_get_config()->client_limit) { if (global.clients >= config_get_config()->client_limit) {
client->respcode = 504; client_send_504(client,
bytes = sock_write(client->con->sock, "The server is already full. Try again later.");
"HTTP/1.0 504 Server Full\r\n" global_unlock();
"Content-Type: text/html\r\n\r\n" avl_tree_unlock(global.source_tree);
"<b>The server is already full. Try again later.</b>\r\n"); return;
if (bytes > 0) client->con->sent_bytes = bytes; }
client_destroy(client); else if(source->max_listeners != -1 &&
source->listeners >= source->max_listeners)
{
client_send_504(client,
"Too many clients on this mountpoint. Try again later.");
global_unlock(); global_unlock();
avl_tree_unlock(global.source_tree); avl_tree_unlock(global.source_tree);
return; return;
} }
global.clients++; global.clients++;
source->listeners++;
global_unlock(); global_unlock();
client->format_data = source->format->create_client_data( client->format_data = source->format->create_client_data(
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <ogg/ogg.h> #include <ogg/ogg.h>
#include <errno.h>
#ifndef _WIN32 #ifndef _WIN32
#include <unistd.h> #include <unistd.h>
...@@ -55,7 +56,8 @@ static void _add_yp_info(source_t *source, char *stat_name, ...@@ -55,7 +56,8 @@ static void _add_yp_info(source_t *source, char *stat_name,
void *info, int type); void *info, int type);
source_t *source_create(client_t *client, connection_t *con, source_t *source_create(client_t *client, connection_t *con,
http_parser_t *parser, const char *mount, format_type_t type) http_parser_t *parser, const char *mount, format_type_t type,
mount_proxy *mountinfo)
{ {
int i = 0; int i = 0;
source_t *src; source_t *src;
...@@ -73,6 +75,8 @@ source_t *source_create(client_t *client, connection_t *con, ...@@ -73,6 +75,8 @@ source_t *source_create(client_t *client, connection_t *con,
src->num_yp_directories = 0; src->num_yp_directories = 0;
src->listeners = 0; src->listeners = 0;
src->send_return = 0; src->send_return = 0;
src->dumpfilename = NULL;
src->dumpfile = NULL;
src->audio_info = util_dict_new(); src->audio_info = util_dict_new();
for (i=0;i<config_get_config()->num_yp_directories;i++) { for (i=0;i<config_get_config()->num_yp_directories;i++) {
if (config_get_config()->yp_url[i]) { if (config_get_config()->yp_url[i]) {
...@@ -86,6 +90,20 @@ source_t *source_create(client_t *client, connection_t *con, ...@@ -86,6 +90,20 @@ source_t *source_create(client_t *client, connection_t *con,
} }
} }
if(mountinfo != NULL) {
src->fallback_mount = mountinfo->fallback_mount;
src->max_listeners = mountinfo->max_listeners;
src->dumpfilename = mountinfo->dumpfile;
}
if(src->dumpfilename != NULL) {
src->dumpfile = fopen(src->dumpfilename, "ab");
if(src->dumpfile == NULL) {
WARN2("Cannot open dump file \"%s\" for appending: %s, disabling.",
src->dumpfilename, strerror(errno));
}
}
return src; return src;
} }
...@@ -170,7 +188,6 @@ void *source_main(void *arg) ...@@ -170,7 +188,6 @@ void *source_main(void *arg)
int listeners = 0; int listeners = 0;
int i=0; int i=0;
int suppress_yp = 0; int suppress_yp = 0;
util_dict *audio_info;
char *ai; char *ai;
long queue_limit = config_get_config()->queue_size_limit; long queue_limit = config_get_config()->queue_size_limit;
...@@ -378,6 +395,18 @@ void *source_main(void *arg) ...@@ -378,6 +395,18 @@ void *source_main(void *arg)
** to catch back up if it can ** to catch back up if it can
*/ */
/* First, stream dumping, if enabled */
if(source->dumpfile) {
if(fwrite(refbuf->data, 1, refbuf->len, source->dumpfile) !=
refbuf->len)
{
WARN1("Write to dump file failed, disabling: %s",
strerror(errno));
fclose(source->dumpfile);
source->dumpfile = NULL;
}
}
/* acquire read lock on client_tree */ /* acquire read lock on client_tree */
avl_tree_rlock(source->client_tree); avl_tree_rlock(source->client_tree);
...@@ -586,6 +615,9 @@ done: ...@@ -586,6 +615,9 @@ done:
avl_delete(global.source_tree, source, source_free_source); avl_delete(global.source_tree, source, source_free_source);
avl_tree_unlock(global.source_tree); avl_tree_unlock(global.source_tree);
if(source->dumpfile)
fclose(source->dumpfile);
thread_exit(0); thread_exit(0);
return NULL; return NULL;
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include "util.h" #include "util.h"
#include "format.h" #include "format.h"
#include <stdio.h>
typedef struct source_tag typedef struct source_tag
{ {
client_t *client; client_t *client;
...@@ -29,13 +31,19 @@ typedef struct source_tag ...@@ -29,13 +31,19 @@ typedef struct source_tag
rwlock_t *shutdown_rwlock; rwlock_t *shutdown_rwlock;
ypdata_t *ypdata[MAX_YP_DIRECTORIES]; ypdata_t *ypdata[MAX_YP_DIRECTORIES];
util_dict *audio_info; util_dict *audio_info;
char *dumpfilename; /* Name of a file to dump incoming stream to */
FILE *dumpfile;
int num_yp_directories; int num_yp_directories;
long listeners; long listeners;
long max_listeners; long max_listeners;
int send_return; int send_return;
} source_t; } source_t;
source_t *source_create(client_t *client, connection_t *con, http_parser_t *parser, const char *mount, format_type_t type); source_t *source_create(client_t *client, connection_t *con,
http_parser_t *parser, const char *mount, format_type_t type,
mount_proxy *mountinfo);
source_t *source_find_mount(const char *mount); source_t *source_find_mount(const char *mount);
int source_compare_sources(void *arg, void *a, void *b); int source_compare_sources(void *arg, void *a, void *b);
int source_free_source(void *key); int source_free_source(void *key);
......
...@@ -414,6 +414,7 @@ const char *util_dict_get(util_dict *dict, const char *key) ...@@ -414,6 +414,7 @@ const char *util_dict_get(util_dict *dict, const char *key)
return dict->val; return dict->val;
dict = dict->next; dict = dict->next;
} }
return NULL;
} }
int util_dict_set(util_dict *dict, const char *key, const char *val) int util_dict_set(util_dict *dict, const char *key, const char *val)
...@@ -521,3 +522,4 @@ char *util_dict_urlencode(util_dict *dict, char delim) ...@@ -521,3 +522,4 @@ char *util_dict_urlencode(util_dict *dict, char delim)
return res; return res;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment