1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-12-04 14:46:30 -05:00

auth sync up. Fix longstanding race bug and make stream start/stop triggers work again.

svn path=/icecast/trunk/icecast/; revision=14114
This commit is contained in:
Karl Heyes 2007-11-08 19:52:51 +00:00
parent b4b8e3e552
commit 66b68170cc
2 changed files with 56 additions and 52 deletions

View File

@ -40,12 +40,13 @@
static mutex_t auth_lock; static mutex_t auth_lock;
static void auth_client_setup (mount_proxy *mountinfo, client_t *client) static auth_client *auth_client_setup (const char *mount, client_t *client)
{ {
/* This will look something like "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" */ /* This will look something like "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" */
const char *header = httpp_getvar(client->parser, "authorization"); const char *header = httpp_getvar(client->parser, "authorization");
char *userpass, *tmp; char *userpass, *tmp;
char *username, *password; char *username, *password;
auth_client *auth_user;
do do
{ {
@ -81,23 +82,35 @@ static void auth_client_setup (mount_proxy *mountinfo, client_t *client)
} while (0); } while (0);
thread_mutex_lock (&mountinfo->auth->lock); auth_user = calloc (1, sizeof(auth_client));
client->auth = mountinfo->auth; auth_user->mount = strdup (mount);
client->auth->refcount++; auth_user->client = client;
DEBUG2 ("...refcount on auth_t %s is %d", client->auth->mount, client->auth->refcount); return auth_user;
thread_mutex_unlock (&mountinfo->auth->lock);
} }
static void queue_auth_client (auth_client *auth_user) static void queue_auth_client (auth_client *auth_user, mount_proxy *mountinfo)
{ {
auth_t *auth; auth_t *auth;
if (auth_user == NULL) if (auth_user == NULL || (mountinfo == NULL && auth_user->client
&& auth_user->client->auth == NULL))
return; return;
auth = auth_user->client->auth;
thread_mutex_lock (&auth->lock);
auth_user->next = NULL; auth_user->next = NULL;
if (mountinfo)
{
auth = mountinfo->auth;
thread_mutex_lock (&auth->lock);
if (auth_user->client)
auth_user->client->auth = auth;
auth->refcount++;
}
else
{
auth = auth_user->client->auth;
thread_mutex_lock (&auth->lock);
}
DEBUG2 ("...refcount on auth_t %s is now %d", auth->mount, auth->refcount);
*auth->tailp = auth_user; *auth->tailp = auth_user;
auth->tailp = &auth_user->next; auth->tailp = &auth_user->next;
auth->pending_count++; auth->pending_count++;
@ -172,7 +185,7 @@ static int is_listener_connected (client_t *client)
/* wrapper function for auth thread to authenticate new listener /* wrapper function for auth thread to authenticate new listener
* connection details * connection details
*/ */
static void auth_new_listener (auth_client *auth_user) static void auth_new_listener (auth_t *auth, auth_client *auth_user)
{ {
client_t *client = auth_user->client; client_t *client = auth_user->client;
@ -184,9 +197,9 @@ static void auth_new_listener (auth_client *auth_user)
client->respcode = 400; client->respcode = 400;
return; return;
} }
if (client->auth->authenticate) if (auth->authenticate)
{ {
if (client->auth->authenticate (auth_user) != AUTH_OK) if (auth->authenticate (auth_user) != AUTH_OK)
return; return;
} }
if (auth_postprocess_listener (auth_user) < 0) if (auth_postprocess_listener (auth_user) < 0)
@ -196,7 +209,7 @@ static void auth_new_listener (auth_client *auth_user)
/* wrapper function for auth thread to drop listener connections /* wrapper function for auth thread to drop listener connections
*/ */
static void auth_remove_listener (auth_client *auth_user) static void auth_remove_listener (auth_t *auth, auth_client *auth_user)
{ {
client_t *client = auth_user->client; client_t *client = auth_user->client;
@ -212,24 +225,22 @@ static void auth_remove_listener (auth_client *auth_user)
/* Callback from auth thread to handle a stream start event, this applies /* Callback from auth thread to handle a stream start event, this applies
* to both source clients and relays. * to both source clients and relays.
*/ */
static void stream_start_callback (auth_client *auth_user) static void stream_start_callback (auth_t *auth, auth_client *auth_user)
{ {
auth_t *auth = auth_user->client->auth;
if (auth->stream_start) if (auth->stream_start)
auth->stream_start (auth_user); auth->stream_start (auth_user);
auth_release (auth);
} }
/* Callback from auth thread to handle a stream start event, this applies /* Callback from auth thread to handle a stream start event, this applies
* to both source clients and relays. * to both source clients and relays.
*/ */
static void stream_end_callback (auth_client *auth_user) static void stream_end_callback (auth_t *auth, auth_client *auth_user)
{ {
auth_t *auth = auth_user->client->auth;
if (auth->stream_end) if (auth->stream_end)
auth->stream_end (auth_user); auth->stream_end (auth_user);
auth_release (auth);
} }
@ -263,7 +274,7 @@ static void *auth_run_thread (void *arg)
auth_user->next = NULL; auth_user->next = NULL;
if (auth_user->process) if (auth_user->process)
auth_user->process (auth_user); auth_user->process (auth, auth_user);
else else
ERROR0 ("client auth process not set"); ERROR0 ("client auth process not set");
@ -282,10 +293,8 @@ static void *auth_run_thread (void *arg)
* on either the active or pending lists. * on either the active or pending lists.
* return 1 if ok to add or 0 to prevent * return 1 if ok to add or 0 to prevent
*/ */
static int check_duplicate_logins (source_t *source, client_t *client) static int check_duplicate_logins (source_t *source, client_t *client, auth_t *auth)
{ {
auth_t *auth = client->auth;
/* allow multiple authenticated relays */ /* allow multiple authenticated relays */
if (client->username == NULL) if (client->username == NULL)
return 1; return 1;
@ -391,6 +400,8 @@ static int add_authenticated_listener (const char *mount, mount_proxy *mountinfo
int ret = 0; int ret = 0;
source_t *source = NULL; source_t *source = NULL;
client->authenticated = 1;
/* Here we are parsing the URI request to see if the extension is .xsl, if /* Here we are parsing the URI request to see if the extension is .xsl, if
* so, then process this request as an XSLT request * so, then process this request as an XSLT request
*/ */
@ -407,7 +418,7 @@ static int add_authenticated_listener (const char *mount, mount_proxy *mountinfo
if (source) if (source)
{ {
if (client->auth && check_duplicate_logins (source, client) == 0) if (check_duplicate_logins (source, client, mountinfo->auth) == 0)
{ {
avl_tree_unlock (global.source_tree); avl_tree_unlock (global.source_tree);
return -1; return -1;
@ -440,7 +451,6 @@ int auth_postprocess_listener (auth_client *auth_user)
ice_config_t *config = config_get_config(); ice_config_t *config = config_get_config();
mount_proxy *mountinfo = config_find_mount (config, auth_user->mount); mount_proxy *mountinfo = config_find_mount (config, auth_user->mount);
client->authenticated = 1;
ret = add_authenticated_listener (auth_user->mount, mountinfo, client); ret = add_authenticated_listener (auth_user->mount, mountinfo, client);
config_release_config(); config_release_config();
@ -468,7 +478,7 @@ void auth_add_listener (const char *mount, client_t *client)
client_send_403 (client, "mountpoint unavailable"); client_send_403 (client, "mountpoint unavailable");
return; return;
} }
if (mountinfo && mountinfo->auth) if (mountinfo && mountinfo->auth && mountinfo->auth->authenticate)
{ {
auth_client *auth_user; auth_client *auth_user;
@ -479,21 +489,11 @@ void auth_add_listener (const char *mount, client_t *client)
client_send_403 (client, "busy, please try again later"); client_send_403 (client, "busy, please try again later");
return; return;
} }
auth_client_setup (mountinfo, client); auth_user = auth_client_setup (mount, client);
config_release_config ();
auth_user = calloc (1, sizeof (auth_client));
if (auth_user == NULL)
{
client_send_401 (client);
return;
}
auth_user->mount = strdup (mount);
auth_user->process = auth_new_listener; auth_user->process = auth_new_listener;
auth_user->client = client;
INFO0 ("adding client for authentication"); INFO0 ("adding client for authentication");
queue_auth_client (auth_user); queue_auth_client (auth_user, mountinfo);
config_release_config ();
} }
else else
{ {
@ -510,18 +510,22 @@ void auth_add_listener (const char *mount, client_t *client)
*/ */
int auth_release_listener (client_t *client) int auth_release_listener (client_t *client)
{ {
if (client->auth) if (client->authenticated)
{ {
auth_client *auth_user = calloc (1, sizeof (auth_client)); const char *mount = httpp_getvar (client->parser, HTTPP_VAR_URI);
if (auth_user == NULL)
return 0;
auth_user->mount = strdup (httpp_getvar (client->parser, HTTPP_VAR_URI)); /* drop any queue reference here, we do not want a race between the source thread
auth_user->process = auth_remove_listener; * and the auth/fserve thread */
auth_user->client = client; client_set_queue (client, NULL);
queue_auth_client (auth_user); if (mount && client->auth && client->auth->release_listener)
return 1; {
auth_client *auth_user = auth_client_setup (mount, client);
auth_user->process = auth_remove_listener;
queue_auth_client (auth_user, NULL);
return 1;
}
client->authenticated = 0;
} }
return 0; return 0;
} }
@ -648,7 +652,7 @@ void auth_stream_start (mount_proxy *mountinfo, const char *mount)
auth_user->mount = strdup (mount); auth_user->mount = strdup (mount);
auth_user->process = stream_start_callback; auth_user->process = stream_start_callback;
queue_auth_client (auth_user); queue_auth_client (auth_user, mountinfo);
} }
} }
} }
@ -667,7 +671,7 @@ void auth_stream_end (mount_proxy *mountinfo, const char *mount)
auth_user->mount = strdup (mount); auth_user->mount = strdup (mount);
auth_user->process = stream_end_callback; auth_user->process = stream_end_callback;
queue_auth_client (auth_user); queue_auth_client (auth_user, mountinfo);
} }
} }
} }

View File

@ -42,7 +42,7 @@ typedef struct auth_client_tag
{ {
char *mount; char *mount;
client_t *client; client_t *client;
void (*process)(struct auth_client_tag *auth_user); void (*process)(struct auth_tag *auth, struct auth_client_tag *auth_user);
struct auth_client_tag *next; struct auth_client_tag *next;
} auth_client; } auth_client;