1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-06-23 06:25:24 +00: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 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==" */
const char *header = httpp_getvar(client->parser, "authorization");
char *userpass, *tmp;
char *username, *password;
auth_client *auth_user;
do
{
@ -81,23 +82,35 @@ static void auth_client_setup (mount_proxy *mountinfo, client_t *client)
} while (0);
thread_mutex_lock (&mountinfo->auth->lock);
client->auth = mountinfo->auth;
client->auth->refcount++;
DEBUG2 ("...refcount on auth_t %s is %d", client->auth->mount, client->auth->refcount);
thread_mutex_unlock (&mountinfo->auth->lock);
auth_user = calloc (1, sizeof(auth_client));
auth_user->mount = strdup (mount);
auth_user->client = client;
return auth_user;
}
static void queue_auth_client (auth_client *auth_user)
static void queue_auth_client (auth_client *auth_user, mount_proxy *mountinfo)
{
auth_t *auth;
if (auth_user == NULL)
if (auth_user == NULL || (mountinfo == NULL && auth_user->client
&& auth_user->client->auth == NULL))
return;
auth = auth_user->client->auth;
thread_mutex_lock (&auth->lock);
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->next;
auth->pending_count++;
@ -172,7 +185,7 @@ static int is_listener_connected (client_t *client)
/* wrapper function for auth thread to authenticate new listener
* 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;
@ -184,9 +197,9 @@ static void auth_new_listener (auth_client *auth_user)
client->respcode = 400;
return;
}
if (client->auth->authenticate)
if (auth->authenticate)
{
if (client->auth->authenticate (auth_user) != AUTH_OK)
if (auth->authenticate (auth_user) != AUTH_OK)
return;
}
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
*/
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;
@ -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
* 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)
auth->stream_start (auth_user);
auth_release (auth);
}
/* Callback from auth thread to handle a stream start event, this applies
* 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)
auth->stream_end (auth_user);
auth_release (auth);
}
@ -263,7 +274,7 @@ static void *auth_run_thread (void *arg)
auth_user->next = NULL;
if (auth_user->process)
auth_user->process (auth_user);
auth_user->process (auth, auth_user);
else
ERROR0 ("client auth process not set");
@ -282,10 +293,8 @@ static void *auth_run_thread (void *arg)
* on either the active or pending lists.
* 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 */
if (client->username == NULL)
return 1;
@ -391,6 +400,8 @@ static int add_authenticated_listener (const char *mount, mount_proxy *mountinfo
int ret = 0;
source_t *source = NULL;
client->authenticated = 1;
/* Here we are parsing the URI request to see if the extension is .xsl, if
* 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 (client->auth && check_duplicate_logins (source, client) == 0)
if (check_duplicate_logins (source, client, mountinfo->auth) == 0)
{
avl_tree_unlock (global.source_tree);
return -1;
@ -440,7 +451,6 @@ int auth_postprocess_listener (auth_client *auth_user)
ice_config_t *config = config_get_config();
mount_proxy *mountinfo = config_find_mount (config, auth_user->mount);
client->authenticated = 1;
ret = add_authenticated_listener (auth_user->mount, mountinfo, client);
config_release_config();
@ -468,7 +478,7 @@ void auth_add_listener (const char *mount, client_t *client)
client_send_403 (client, "mountpoint unavailable");
return;
}
if (mountinfo && mountinfo->auth)
if (mountinfo && mountinfo->auth && mountinfo->auth->authenticate)
{
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");
return;
}
auth_client_setup (mountinfo, 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 = auth_client_setup (mount, client);
auth_user->process = auth_new_listener;
auth_user->client = client;
INFO0 ("adding client for authentication");
queue_auth_client (auth_user);
queue_auth_client (auth_user, mountinfo);
config_release_config ();
}
else
{
@ -510,18 +510,22 @@ void auth_add_listener (const char *mount, 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));
if (auth_user == NULL)
return 0;
const char *mount = httpp_getvar (client->parser, HTTPP_VAR_URI);
auth_user->mount = strdup (httpp_getvar (client->parser, HTTPP_VAR_URI));
auth_user->process = auth_remove_listener;
auth_user->client = client;
/* drop any queue reference here, we do not want a race between the source thread
* and the auth/fserve thread */
client_set_queue (client, NULL);
queue_auth_client (auth_user);
return 1;
if (mount && client->auth && client->auth->release_listener)
{
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;
}
@ -648,7 +652,7 @@ void auth_stream_start (mount_proxy *mountinfo, const char *mount)
auth_user->mount = strdup (mount);
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->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;
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;
} auth_client;