mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2025-02-02 15:07:36 -05:00
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
This commit is contained in:
parent
d2fbef6058
commit
c359faf1de
11
src/client.c
11
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"
|
||||
"<b>%s</b>\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"
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
@ -311,6 +312,15 @@ int connection_create_source(client_t *client, connection_t *con, http_parser_t
|
||||
|
||||
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");
|
||||
|
||||
if (contenttype != NULL) {
|
||||
@ -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"
|
||||
"<b>The server is already full. Try again later.</b>\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"
|
||||
"<b>The server is already full. Try again later.</b>\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(
|
||||
|
36
src/source.c
36
src/source.c
@ -3,6 +3,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
@ -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;i<config_get_config()->num_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;
|
||||
|
10
src/source.h
10
src/source.h
@ -6,6 +6,8 @@
|
||||
#include "util.h"
|
||||
#include "format.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user