diff --git a/src/client.c b/src/client.c
index ea350218..11fdfc5d 100644
--- a/src/client.c
+++ b/src/client.c
@@ -69,6 +69,17 @@ void client_send_404(client_t *client, char *message) {
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"
+ "%s\r\n", message);
+ if (bytes > 0) client->con->sent_bytes = bytes;
+ client_destroy(client);
+}
+
void client_send_401(client_t *client) {
int bytes = sock_write(client->con->sock,
"HTTP/1.0 401 Authentication Required\r\n"
diff --git a/src/client.h b/src/client.h
index 4ae65bf3..310584d2 100644
--- a/src/client.h
+++ b/src/client.h
@@ -29,6 +29,7 @@ typedef struct _client_tag
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_404(client_t *client, char *message);
void client_send_401(client_t *client);
void client_send_400(client_t *client, char *message);
diff --git a/src/connection.c b/src/connection.c
index ef73fb5f..52f1e14f 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -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) {
source_t *source;
char *contenttype;
+ mount_proxy *mountproxy, *mountinfo = NULL;
/* check to make sure this source wouldn't
** be over the limit
@@ -310,6 +311,15 @@ int connection_create_source(client_t *client, connection_t *con, http_parser_t
global_unlock();
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");
@@ -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);
goto fail;
} else {
- source = source_create(client, con, parser, mount, format);
+ source = source_create(client, con, parser, mount,
+ format, mountinfo);
}
} else {
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.");
- source = source_create(client, con, parser, mount, format);
+ source = source_create(client, con, parser, mount, format, mountinfo);
}
source->send_return = 1;
@@ -762,13 +773,8 @@ static void _handle_get_request(connection_t *con,
global_lock();
if (global.clients >= config_get_config()->client_limit) {
- 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"
- "The server is already full. Try again later.\r\n");
- if (bytes > 0) client->con->sent_bytes = bytes;
- client_destroy(client);
+ client_send_504(client,
+ "The server is already full. Try again later.");
global_unlock();
return;
}
@@ -781,18 +787,23 @@ static void _handle_get_request(connection_t *con,
global_lock();
if (global.clients >= config_get_config()->client_limit) {
- 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"
- "The server is already full. Try again later.\r\n");
- if (bytes > 0) client->con->sent_bytes = bytes;
- client_destroy(client);
+ client_send_504(client,
+ "The server is already full. Try again later.");
global_unlock();
avl_tree_unlock(global.source_tree);
return;
}
+ 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();
+ avl_tree_unlock(global.source_tree);
+ return;
+ }
global.clients++;
+ source->listeners++;
global_unlock();
client->format_data = source->format->create_client_data(
diff --git a/src/source.c b/src/source.c
index 300f49ab..b8274cab 100644
--- a/src/source.c
+++ b/src/source.c
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#ifndef _WIN32
#include
@@ -55,7 +56,8 @@ static void _add_yp_info(source_t *source, char *stat_name,
void *info, int type);
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;
source_t *src;
@@ -73,6 +75,8 @@ source_t *source_create(client_t *client, connection_t *con,
src->num_yp_directories = 0;
src->listeners = 0;
src->send_return = 0;
+ src->dumpfilename = NULL;
+ src->dumpfile = NULL;
src->audio_info = util_dict_new();
for (i=0;inum_yp_directories;i++) {
if (config_get_config()->yp_url[i]) {
@@ -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;
}
@@ -170,7 +188,6 @@ void *source_main(void *arg)
int listeners = 0;
int i=0;
int suppress_yp = 0;
- util_dict *audio_info;
char *ai;
long queue_limit = config_get_config()->queue_size_limit;
@@ -378,6 +395,18 @@ void *source_main(void *arg)
** 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 */
avl_tree_rlock(source->client_tree);
@@ -586,6 +615,9 @@ done:
avl_delete(global.source_tree, source, source_free_source);
avl_tree_unlock(global.source_tree);
+ if(source->dumpfile)
+ fclose(source->dumpfile);
+
thread_exit(0);
return NULL;
diff --git a/src/source.h b/src/source.h
index 4a2701a8..842005b2 100644
--- a/src/source.h
+++ b/src/source.h
@@ -6,6 +6,8 @@
#include "util.h"
#include "format.h"
+#include
+
typedef struct source_tag
{
client_t *client;
@@ -29,13 +31,19 @@ typedef struct source_tag
rwlock_t *shutdown_rwlock;
ypdata_t *ypdata[MAX_YP_DIRECTORIES];
util_dict *audio_info;
+
+ char *dumpfilename; /* Name of a file to dump incoming stream to */
+ FILE *dumpfile;
+
int num_yp_directories;
long listeners;
long max_listeners;
int send_return;
} 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);
int source_compare_sources(void *arg, void *a, void *b);
int source_free_source(void *key);
diff --git a/src/util.c b/src/util.c
index cd49d582..666fab2c 100644
--- a/src/util.c
+++ b/src/util.c
@@ -414,6 +414,7 @@ const char *util_dict_get(util_dict *dict, const char *key)
return dict->val;
dict = dict->next;
}
+ return NULL;
}
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)
return res;
}
+