diff --git a/NEWS b/NEWS index dc1332f0..2f6ae0d7 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,21 @@ Feature differences from SVN trunk any extra tags are show in the conf/icecast.xml.dist file +2.3-kh29 +. some small code re-organisation in kh28 caused auth htpasswd to fail new +listeners +. work around FBSD issue with listening on IPv4/IPv6 sockets + +2.3-kh28 +. race fix in yp thread startup. +. manageauth userlist page was blank due to a NULL check, fixed. +. add rejected_mount auth option to redirect unathenticated listeners to an + alternative mountpoint. eg subscription stream redirected to low bitrate +. Allow for url auth to handle 'Mountpoint: ' header for redirecting listeners + if they are to be rejected to an alternative mountpoint on the same server. + This is as opposed to the Location: header which gets a player to redirect, + maybe to an alternative server. + 2.3-kh27 . fix potential fserve thread race . merge listener inline shoutcast metadata into previous block write. It is diff --git a/configure.in b/configure.in index 2d3f2be0..37496726 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -AC_INIT([Icecast], [2.3-kh27], [karl@xiph.org]) +AC_INIT([Icecast], [2.3-kh29], [karl@xiph.org]) AC_PREREQ(2.59) AC_CONFIG_SRCDIR(src/main.c) diff --git a/src/admin.c b/src/admin.c index 14ecaf6d..104dc8d1 100644 --- a/src/admin.c +++ b/src/admin.c @@ -759,7 +759,7 @@ static void command_manageauth(client_t *client, source_t *source, COMMAND_OPTIONAL (client, "username", username); if (action == NULL) - break; + action = "list"; if (!strcmp(action, "add")) { diff --git a/src/auth.c b/src/auth.c index 2d69589d..5b8eb05a 100644 --- a/src/auth.c +++ b/src/auth.c @@ -43,6 +43,7 @@ static spin_t auth_lock; static volatile int thread_id; static void *auth_run_thread (void *arg); +static int auth_postprocess_listener (auth_client *auth_user); void auth_check_http (client_t *client) @@ -222,8 +223,14 @@ static void auth_new_listener (auth_client *auth_user) } if (auth_user->auth->authenticate) { - if (auth_user->auth->authenticate (auth_user) != AUTH_OK) - return; + switch (auth_user->auth->authenticate (auth_user)) + { + case AUTH_OK: + case AUTH_FAILED: + break; + default: + return; + } } if (auth_postprocess_listener (auth_user) < 0) INFO1 ("client %lu failed", client->con->id); @@ -556,15 +563,31 @@ static int add_authenticated_listener (const char *mount, mount_proxy *mountinfo } -int auth_postprocess_listener (auth_client *auth_user) +static int auth_postprocess_listener (auth_client *auth_user) { int ret; client_t *client = auth_user->client; - ice_config_t *config = config_get_config(); + auth_t *auth = auth_user->auth; + ice_config_t *config; + mount_proxy *mountinfo; + const char *mount = auth_user->mount; - mount_proxy *mountinfo = config_find_mount (config, auth_user->mount); + if (client == NULL) + return 0; - ret = add_authenticated_listener (auth_user->mount, mountinfo, client); + if (client->authenticated == 0) + { + /* auth failed so check to placing listeners elsewhere */ + if (auth_user->rejected_mount) + mount = auth_user->rejected_mount; + else if (auth->rejected_mount) + mount = auth->rejected_mount; + else + return 0; + } + config = config_get_config(); + mountinfo = config_find_mount (config, mount); + ret = add_authenticated_listener (mount, mountinfo, client); config_release_config(); auth_user->client = NULL; @@ -715,6 +738,8 @@ static int get_authenticator (auth_t *auth, config_options_t *options) auth->realm = (char*)xmlStrdup (XMLSTR(options->value)); else if (strcmp(options->name, "drop_existing_listener") == 0) auth->drop_existing_listener = atoi (options->value); + else if (strcmp (options->name, "rejected_mount") == 0) + auth->rejected_mount = (char*)xmlStrdup (XMLSTR(options->value)); else if (strcmp(options->name, "handlers") == 0) auth->handlers = atoi (options->value); options = options->next; diff --git a/src/auth.h b/src/auth.h index 4b05d192..a6a7cbb4 100644 --- a/src/auth.h +++ b/src/auth.h @@ -42,10 +42,11 @@ typedef struct auth_client_tag char *mount; char *hostname; int port; + int handler; client_t *client; struct auth_tag *auth; + char *rejected_mount; void *thread_data; - int handler; void (*process)(struct auth_client_tag *auth_user); struct auth_client_tag *next; } auth_client; @@ -96,6 +97,9 @@ typedef struct auth_tag int drop_existing_listener; int handlers; + /* mountpoint to send unauthenticated listeners */ + char *rejected_mount; + /* runtime allocated array of thread handlers for this auth */ auth_thread_t *handles; @@ -127,10 +131,6 @@ void auth_stream_end (struct _mount_proxy *mountinfo, const char *mount); int auth_stream_authenticate (client_t *client, const char *mount, struct _mount_proxy *mountinfo); -/* called from auth thread, after the client has successfully authenticated - * and requires adding to source or fserve. */ -int auth_postprocess_listener (auth_client *auth_user); - /* called from auth thread */ void auth_postprocess_source (auth_client *auth_user); diff --git a/src/auth_htpasswd.c b/src/auth_htpasswd.c index e207c3d9..46526053 100644 --- a/src/auth_htpasswd.c +++ b/src/auth_htpasswd.c @@ -195,6 +195,7 @@ static auth_result htpasswd_auth (auth_client *auth_user) if (strcmp (found->pass, hashed_pw) == 0) { free (hashed_pw); + client->authenticated = 1; return AUTH_OK; } free (hashed_pw); diff --git a/src/auth_url.c b/src/auth_url.c index 1cf20b4d..3ddf52d1 100644 --- a/src/auth_url.c +++ b/src/auth_url.c @@ -186,6 +186,12 @@ static int handle_returned_header (void *ptr, size_t size, size_t nmemb, void *s atd->location = malloc (len+1); snprintf (atd->location, len+1, "%s", (char *)ptr+10); } + if (strncasecmp (ptr, "Mountpoint: ", 12) == 0) + { + int len = strcspn ((char*)ptr+12, "\r\n"); + auth_user->rejected_mount = malloc (len+1); + snprintf (auth_user->rejected_mount, len+1, "%s", (char *)ptr+12); + } } return (int)bytes; diff --git a/src/source.c b/src/source.c index 04c3ceff..8d458cce 100644 --- a/src/source.c +++ b/src/source.c @@ -1251,18 +1251,15 @@ 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) { - source->timeout = config->source_timeout; - - /* handle fallback to file specially */ + /* skip if source is a fallback to file */ if (source->running && source->client == NULL) { stats_event_hidden (source->mount, NULL, 1); - if (mountinfo && mountinfo->source_timeout > 0) - source->timeout = mountinfo->source_timeout; return; } /* set global settings first */ source->queue_size_limit = config->queue_size_limit; + source->timeout = config->source_timeout; source->burst_size = config->burst_size; stats_event_args (source->mount, "listenurl", "http://%s:%d%s", @@ -1454,7 +1451,6 @@ static void *source_fallback_file (void *arg) source->parser = parser; source->avg_bitrate_duration = 20; source->listener_send_trigger = 4096; - source->on_demand = 1; file = NULL; if (connection_complete_source (source, 0) < 0) diff --git a/src/yp.c b/src/yp.c index f3570ec5..7cfe5887 100644 --- a/src/yp.c +++ b/src/yp.c @@ -665,6 +665,7 @@ static void *yp_update_thread(void *arg) { struct yp_server *server; + yp_thread = thread_self(); /* DEBUG0("YP thread started"); */ /* do the YP communication */ @@ -937,6 +938,6 @@ void yp_shutdown (void) void yp_thread_startup (void) { if (yp_thread == NULL) - yp_thread = thread_create ("YP Thread", yp_update_thread, NULL, THREAD_DETACHED); + thread_create ("YP Thread", yp_update_thread, NULL, THREAD_DETACHED); } diff --git a/win32/icecast2.iss b/win32/icecast2.iss index 2af54d06..1bb54c38 100644 --- a/win32/icecast2.iss +++ b/win32/icecast2.iss @@ -3,7 +3,7 @@ [Setup] AppName=Icecast2-KH -AppVerName=Icecast v2.3.1-kh27 +AppVerName=Icecast v2.3.1-kh29 AppPublisherURL=http://www.icecast.org AppSupportURL=http://www.icecast.org AppUpdatesURL=http://www.icecast.org @@ -13,7 +13,7 @@ AllowNoIcons=yes LicenseFile=..\COPYING InfoAfterFile=..\README OutputDir=. -OutputBaseFilename=icecast2_win32_v2.3.1-kh27_setup +OutputBaseFilename=icecast2_win32_v2.3.1-kh29_setup WizardImageFile=icecast2logo2.bmp WizardImageStretch=no ; uncomment the following line if you want your installation to run on NT 3.51 too.