mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-09-29 04:25:55 -04:00
various merges from trunk due to rc1 testing. slave relay user/pass checked
no matter if listener auth set. small memory leaks fixed. svn path=/icecast/branches/kh/icecast/; revision=9856
This commit is contained in:
parent
787f86116e
commit
d786d8d2e4
@ -381,7 +381,7 @@ If you are relaying a Shoutcast stream, you need to specify this indicator to al
|
||||
<username>othersource</username>
|
||||
<password>hackmemore</password>
|
||||
<max-listeners>1</max-listeners>
|
||||
<listening-duration>3600</listening-duration>
|
||||
<max-listener-duration>3600</max-listener-duration>
|
||||
<dump-file>/tmp/dump-example1.ogg</dump-file>
|
||||
<intro>/intro.ogg</intro>
|
||||
<fallback-mount>/example2.ogg</fallback-mount>
|
||||
@ -480,9 +480,9 @@ listening clients back from the fallback mount.
|
||||
</div>
|
||||
<h4>fallback-when-full</h4>
|
||||
<div class="indentedbox">
|
||||
<p>When set to 1, this will cause new listeners (when the max listener has been reached)
|
||||
to move to the fallback mount if there is one specified.
|
||||
</p>
|
||||
<p>When set to 1, this will cause new listeners, when the max listener count for the
|
||||
mountpoint has been reached, to move to the fallback mount if there is one specified.
|
||||
</p>
|
||||
</div>
|
||||
<h4>no-yp</h4>
|
||||
<div class="indentedbox">
|
||||
|
23
src/auth.c
23
src/auth.c
@ -311,9 +311,12 @@ static int add_authenticated_client (const char *mount, mount_proxy *mountinfo,
|
||||
avl_tree_unlock (global.source_tree);
|
||||
return -1;
|
||||
}
|
||||
/* set a per-mount disconnect time if auth hasn't set one already */
|
||||
if (mountinfo->max_listener_duration && client->con->discon_time == 0)
|
||||
client->con->discon_time = time(NULL) + mountinfo->max_listener_duration;
|
||||
if (mountinfo)
|
||||
{
|
||||
/* set a per-mount disconnect time if auth hasn't set one already */
|
||||
if (mountinfo->max_listener_duration && client->con->discon_time == 0)
|
||||
client->con->discon_time = time(NULL) + mountinfo->max_listener_duration;
|
||||
}
|
||||
|
||||
ret = add_client_to_source (source, client);
|
||||
avl_tree_unlock (global.source_tree);
|
||||
@ -359,11 +362,17 @@ int auth_postprocess_client (auth_client *auth_user)
|
||||
void add_client (const char *mount, client_t *client)
|
||||
{
|
||||
mount_proxy *mountinfo;
|
||||
ice_config_t *config = config_get_config();
|
||||
ice_config_t *config;
|
||||
|
||||
/* we don't need any more data from the listener, just setup for writing */
|
||||
client->refbuf->len = PER_CLIENT_REFBUF_SIZE;
|
||||
|
||||
if (connection_check_relay_pass(client->parser))
|
||||
{
|
||||
client_as_slave (client);
|
||||
INFO0 ("client connected as slave");
|
||||
}
|
||||
config = config_get_config();
|
||||
mountinfo = config_find_mount (config, mount);
|
||||
if (mountinfo && mountinfo->no_mount)
|
||||
{
|
||||
@ -390,12 +399,6 @@ void add_client (const char *mount, client_t *client)
|
||||
client_send_401 (client);
|
||||
return;
|
||||
}
|
||||
/* config lock taken in here */
|
||||
if (connection_check_relay_pass(client->parser))
|
||||
{
|
||||
client_as_slave (client);
|
||||
INFO0 ("client connected as slave");
|
||||
}
|
||||
auth_user = calloc (1, sizeof (auth_client));
|
||||
if (auth_user == NULL)
|
||||
{
|
||||
|
@ -191,6 +191,8 @@ void config_clear(ice_config_t *c)
|
||||
xmlFree(c->webroot_dir);
|
||||
if (c->adminroot_dir && c->adminroot_dir != CONFIG_DEFAULT_ADMINROOT_DIR)
|
||||
xmlFree(c->adminroot_dir);
|
||||
if (c->cert_file)
|
||||
xmlFree(c->cert_file);
|
||||
if (c->pidfile)
|
||||
xmlFree(c->pidfile);
|
||||
if (c->playlist_log && c->playlist_log != CONFIG_DEFAULT_PLAYLIST_LOG)
|
||||
|
18
src/client.c
18
src/client.c
@ -37,18 +37,22 @@
|
||||
#include "client.h"
|
||||
#include "logging.h"
|
||||
|
||||
#undef CATMODULE
|
||||
#define CATMODULE "client"
|
||||
|
||||
#ifdef HAVE_AIO
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
/* should be called with global lock held */
|
||||
#undef CATMODULE
|
||||
#define CATMODULE "client"
|
||||
|
||||
/* create a client_t with the provided connection and parser details. Return
|
||||
* 0 on success, -1 if server limit has been reached. In either case a
|
||||
* client_t is returned just in case a message needs to be returned. Should
|
||||
* be called with global lock held.
|
||||
*/
|
||||
int client_create (client_t **c_ptr, connection_t *con, http_parser_t *parser)
|
||||
{
|
||||
ice_config_t *config;
|
||||
@ -56,7 +60,7 @@ int client_create (client_t **c_ptr, connection_t *con, http_parser_t *parser)
|
||||
int ret = -1;
|
||||
|
||||
if (client == NULL)
|
||||
return -1;
|
||||
abort();
|
||||
|
||||
config = config_get_config ();
|
||||
|
||||
@ -71,6 +75,8 @@ int client_create (client_t **c_ptr, connection_t *con, http_parser_t *parser)
|
||||
stats_event_args (NULL, "clients", "%d", global.clients);
|
||||
client->con = con;
|
||||
client->parser = parser;
|
||||
client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE);
|
||||
client->refbuf->len = 0; /* force reader code to ignore buffer contents */
|
||||
client->pos = 0;
|
||||
client->write_to_client = format_generic_write_to_client;
|
||||
*c_ptr = client;
|
||||
|
@ -105,9 +105,9 @@ static volatile client_queue_t *_req_queue = NULL, **_req_queue_tail = &_req_que
|
||||
static volatile client_queue_t *_con_queue = NULL, **_con_queue_tail = &_con_queue;
|
||||
static mutex_t _con_queue_mutex;
|
||||
static mutex_t _req_queue_mutex;
|
||||
static int ssl_ok;
|
||||
#ifdef HAVE_OPENSSL
|
||||
static SSL_CTX *ssl_ctx;
|
||||
static int ssl_ok;
|
||||
#endif
|
||||
|
||||
rwlock_t _source_shutdown_rwlock;
|
||||
@ -131,6 +131,7 @@ void connection_initialize(void)
|
||||
|
||||
static void get_ssl_certificate ()
|
||||
{
|
||||
ssl_ok = 0;
|
||||
#ifdef HAVE_OPENSSL
|
||||
SSL_METHOD *method;
|
||||
ice_config_t *config;
|
||||
@ -141,7 +142,6 @@ static void get_ssl_certificate ()
|
||||
method = SSLv23_server_method();
|
||||
ssl_ctx = SSL_CTX_new (method);
|
||||
|
||||
ssl_ok = 0;
|
||||
config = config_get_config ();
|
||||
do
|
||||
{
|
||||
@ -280,11 +280,13 @@ connection_t *connection_create (sock_t sock, sock_t serversock, char *ip)
|
||||
*/
|
||||
void connection_uses_ssl (connection_t *con)
|
||||
{
|
||||
#ifdef HAVE_OPENSSL
|
||||
con->read = connection_read_ssl;
|
||||
con->send = connection_send_ssl;
|
||||
con->ssl = SSL_new (ssl_ctx);
|
||||
SSL_set_accept_state (con->ssl);
|
||||
SSL_set_fd (con->ssl, con->sock);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -561,9 +563,7 @@ void connection_accept_loop(void)
|
||||
global_unlock();
|
||||
|
||||
/* setup client for reading incoming http */
|
||||
client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE);
|
||||
client->refbuf->data [PER_CLIENT_REFBUF_SIZE-1] = '\000';
|
||||
client->refbuf->len = 0; /* force reader code to ignore buffer */
|
||||
|
||||
node = calloc (1, sizeof (client_queue_t));
|
||||
if (node == NULL)
|
||||
@ -611,7 +611,7 @@ void connection_accept_loop(void)
|
||||
/* Called when activating a source. Verifies that the source count is not
|
||||
* exceeded and applies any initial parameters.
|
||||
*/
|
||||
int connection_complete_source (source_t *source, connection_t *con, http_parser_t *in_parser)
|
||||
int connection_complete_source (source_t *source, connection_t *con, http_parser_t *in_parser, int response)
|
||||
{
|
||||
ice_config_t *config = config_get_config();
|
||||
|
||||
@ -638,8 +638,11 @@ int connection_complete_source (source_t *source, connection_t *con, http_parser
|
||||
{
|
||||
global_unlock();
|
||||
config_release_config();
|
||||
if (source->client)
|
||||
if (response)
|
||||
{
|
||||
client_send_404 (source->client, "Content-type not supported");
|
||||
source->client = NULL;
|
||||
}
|
||||
WARN1("Content-type \"%s\" not supported, dropping source", contenttype);
|
||||
return -1;
|
||||
}
|
||||
@ -655,27 +658,15 @@ int connection_complete_source (source_t *source, connection_t *con, http_parser
|
||||
{
|
||||
global_unlock();
|
||||
config_release_config();
|
||||
if (source->client)
|
||||
if (response)
|
||||
{
|
||||
client_send_404 (source->client, "internal format allocation problem");
|
||||
source->client = NULL;
|
||||
}
|
||||
WARN1 ("plugin format failed for \"%s\"", source->mount);
|
||||
source->client = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* for relays, we don't yet have a client, however we do require one
|
||||
* to retrieve the stream from. This is created here, quite late,
|
||||
* because we can't use this client to return an error code/message,
|
||||
* so we only do this once we know we're going to accept the source.
|
||||
*/
|
||||
if (source->client == NULL)
|
||||
{
|
||||
if (client_create (&source->client, con, parser) < 0)
|
||||
{
|
||||
config_release_config();
|
||||
global_unlock();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
global.sources++;
|
||||
stats_event_args (NULL, "sources", "%d", global.sources);
|
||||
global_unlock();
|
||||
@ -698,8 +689,11 @@ int connection_complete_source (source_t *source, connection_t *con, http_parser
|
||||
global_unlock();
|
||||
config_release_config();
|
||||
|
||||
if (source->client)
|
||||
if (response)
|
||||
{
|
||||
client_send_404 (source->client, "too many sources connected");
|
||||
source->client = NULL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -885,9 +879,8 @@ static void _handle_source_request (client_t *client, char *uri, int auth_style)
|
||||
source->shoutcast_compat = 1;
|
||||
}
|
||||
source->client = client;
|
||||
if (connection_complete_source (source, NULL, NULL) < 0)
|
||||
if (connection_complete_source (source, NULL, NULL, 1) < 0)
|
||||
{
|
||||
source->client = NULL;
|
||||
source_free_source (source);
|
||||
}
|
||||
else
|
||||
|
@ -56,7 +56,7 @@ void connection_accept_loop(void);
|
||||
void connection_close(connection_t *con);
|
||||
connection_t *connection_create (sock_t sock, sock_t serversock, char *ip);
|
||||
int connection_complete_source (struct source_tag *source, connection_t *con,
|
||||
http_parser_t *parser);
|
||||
http_parser_t *parser, int response);
|
||||
|
||||
int connection_check_source_pass(http_parser_t *parser, const char *mount);
|
||||
int connection_check_relay_pass(http_parser_t *parser);
|
||||
|
@ -160,7 +160,7 @@ int format_check_file_buffer (source_t *source, client_t *client)
|
||||
if (refbuf == NULL)
|
||||
{
|
||||
/* client refers to no data, must be from a move */
|
||||
if (source->client->con)
|
||||
if (source->client)
|
||||
{
|
||||
find_client_start (source, client);
|
||||
return -1;
|
||||
|
@ -409,8 +409,7 @@ static void format_mp3_free_plugin (format_plugin_t *plugin)
|
||||
free (format_mp3->url_artist);
|
||||
free (format_mp3->url_title);
|
||||
refbuf_release (format_mp3->metadata);
|
||||
if (format_mp3->read_data)
|
||||
refbuf_release (format_mp3->read_data);
|
||||
refbuf_release (format_mp3->read_data);
|
||||
free(format_mp3);
|
||||
free(plugin);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
/* the global log descriptors */
|
||||
|
@ -313,6 +313,7 @@ static int _server_proc_init(void)
|
||||
_fatal_error("Failed trying to listen on server socket");
|
||||
return 0;
|
||||
}
|
||||
|
||||
config = config_get_config_unlocked();
|
||||
/* recreate the pid file */
|
||||
if (config->pidfile)
|
||||
|
@ -66,6 +66,8 @@ void refbuf_addref(refbuf_t *self)
|
||||
|
||||
void refbuf_release(refbuf_t *self)
|
||||
{
|
||||
if (self == NULL)
|
||||
return;
|
||||
self->_count--;
|
||||
if (self->_count == 0) {
|
||||
while (self->associated)
|
||||
|
17
src/slave.c
17
src/slave.c
@ -309,7 +309,18 @@ static void *start_relay_stream (void *arg)
|
||||
ERROR1("Error from relay request: %s", httpp_getvar(parser, HTTPP_VAR_ERROR_MESSAGE));
|
||||
break;
|
||||
}
|
||||
if (connection_complete_source (src, con, parser) < 0)
|
||||
|
||||
if (client_create (&src->client, con, parser) < 0)
|
||||
{
|
||||
/* make sure only the client_destory frees these */
|
||||
con = NULL;
|
||||
parser = NULL;
|
||||
streamsock = SOCK_ERROR;
|
||||
break;
|
||||
}
|
||||
client_set_queue (src->client, NULL);
|
||||
|
||||
if (connection_complete_source (src, con, parser, 0) < 0)
|
||||
{
|
||||
DEBUG0("Failed to complete source initialisation");
|
||||
break;
|
||||
@ -325,6 +336,7 @@ static void *start_relay_stream (void *arg)
|
||||
yp_remove (relay->localmount);
|
||||
relay->source->yp_public = -1;
|
||||
}
|
||||
|
||||
/* initiate an immediate relay cleanup run */
|
||||
relay->cleanup = 1;
|
||||
rescan_relays = 1;
|
||||
@ -745,11 +757,12 @@ static void *streamlist_thread (void *arg)
|
||||
static void update_from_master (ice_config_t *config)
|
||||
{
|
||||
#ifdef HAVE_CURL
|
||||
struct master_conn_details *details = calloc (1, sizeof (*details));
|
||||
struct master_conn_details *details;
|
||||
|
||||
if (config->master_password == NULL || config->master_server == NULL ||
|
||||
config->master_server_port == 0)
|
||||
return;
|
||||
details = calloc (1, sizeof (*details));
|
||||
details->server = strdup (config->master_server);
|
||||
details->port = config->master_server_port;
|
||||
details->ssl_port = config->master_ssl_port;
|
||||
|
24
src/source.c
24
src/source.c
@ -356,7 +356,7 @@ void source_move_clients (source_t *source, source_t *dest)
|
||||
{
|
||||
client_set_queue (client, NULL);
|
||||
client->check_buffer = format_check_file_buffer;
|
||||
if (source->client && source->client->con == NULL)
|
||||
if (source->client == NULL)
|
||||
client->intro_offset = -1;
|
||||
}
|
||||
|
||||
@ -415,7 +415,7 @@ static void get_next_buffer (source_t *source)
|
||||
|
||||
thread_mutex_unlock (&source->lock);
|
||||
|
||||
if (source->client->con)
|
||||
if (source->client)
|
||||
fds = util_timed_wait_for_fd (source->client->con->sock, delay);
|
||||
else
|
||||
{
|
||||
@ -687,11 +687,14 @@ static void source_init (source_t *source)
|
||||
|
||||
source->fast_clients_p = &source->active_clients;
|
||||
source->audio_info = util_dict_new();
|
||||
str = httpp_getvar(source->client->parser, "ice-audio-info");
|
||||
if (str)
|
||||
if (source->client)
|
||||
{
|
||||
_parse_audio_info (source, str);
|
||||
stats_event (source->mount, "audio_info", str);
|
||||
str = httpp_getvar(source->client->parser, "ice-audio-info");
|
||||
if (str)
|
||||
{
|
||||
_parse_audio_info (source, str);
|
||||
stats_event (source->mount, "audio_info", str);
|
||||
}
|
||||
}
|
||||
|
||||
thread_mutex_unlock (&source->lock);
|
||||
@ -1119,7 +1122,7 @@ 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)
|
||||
{
|
||||
/* skip if source is a fallback to file */
|
||||
if (source->running && source->client->con == NULL)
|
||||
if (source->running && source->client == NULL)
|
||||
{
|
||||
stats_event_hidden (source->mount, NULL, 1);
|
||||
return;
|
||||
@ -1203,8 +1206,8 @@ void source_client_callback (client_t *client, void *arg)
|
||||
global_lock();
|
||||
global.sources--;
|
||||
global_unlock();
|
||||
source_clear_source (source);
|
||||
source_free_source (source);
|
||||
client_destroy (client);
|
||||
return;
|
||||
}
|
||||
client->refbuf = old_data->associated;
|
||||
@ -1237,7 +1240,7 @@ static void source_run_script (char *command, char *mountpoint)
|
||||
break;
|
||||
case 0: /* child */
|
||||
DEBUG1 ("Starting command %s", command);
|
||||
execl (command, command, mountpoint, NULL);
|
||||
execl (command, command, mountpoint, (char*)NULL);
|
||||
ERROR2 ("Unable to run command %s (%s)", command, strerror (errno));
|
||||
exit(0);
|
||||
default: /* parent */
|
||||
@ -1304,9 +1307,10 @@ static void *source_fallback_file (void *arg)
|
||||
source->intro_file = file;
|
||||
file = NULL;
|
||||
|
||||
if (connection_complete_source (source, NULL, parser) < 0)
|
||||
if (connection_complete_source (source, NULL, parser, 0) < 0)
|
||||
break;
|
||||
source_client_thread (source);
|
||||
httpp_destroy (parser);
|
||||
} while (0);
|
||||
if (file)
|
||||
fclose (file);
|
||||
|
12
src/util.c
12
src/util.c
@ -722,12 +722,18 @@ long rate_avg (struct rate_calc *calc)
|
||||
|
||||
void rate_free (struct rate_calc *calc)
|
||||
{
|
||||
int i = calc->seconds;
|
||||
struct rate_calc_node *endoflist;
|
||||
|
||||
for (; i; i--)
|
||||
if (calc == NULL)
|
||||
return;
|
||||
endoflist = calc->current;
|
||||
while (calc->current)
|
||||
{
|
||||
struct rate_calc_node *to_go = calc->current;
|
||||
calc->current = to_go->next;
|
||||
if (to_go->next == endoflist)
|
||||
calc->current = NULL;
|
||||
else
|
||||
calc->current = to_go->next;
|
||||
free (to_go);
|
||||
}
|
||||
free (calc);
|
||||
|
2
src/yp.c
2
src/yp.c
@ -602,7 +602,7 @@ static void check_servers ()
|
||||
|
||||
source_t *source = node->key;
|
||||
thread_mutex_lock (&source->lock);
|
||||
if ((yp = create_yp_entry (source->mount)) != NULL)
|
||||
if (source->yp_public && (yp = create_yp_entry (source->mount)) != NULL)
|
||||
{
|
||||
DEBUG1 ("Adding existing mount %s", source->mount);
|
||||
yp->server = server;
|
||||
|
Loading…
Reference in New Issue
Block a user