[xiph-commits] r14114 - icecast/trunk/icecast/src

karl at svn.xiph.org karl at svn.xiph.org
Thu Nov 8 11:52:52 PST 2007


Author: karl
Date: 2007-11-08 11:52:51 -0800 (Thu, 08 Nov 2007)
New Revision: 14114

Modified:
   icecast/trunk/icecast/src/auth.c
   icecast/trunk/icecast/src/auth.h
Log:
auth sync up. Fix longstanding race bug and make stream start/stop triggers work again.


Modified: icecast/trunk/icecast/src/auth.c
===================================================================
--- icecast/trunk/icecast/src/auth.c	2007-11-08 13:57:27 UTC (rev 14113)
+++ icecast/trunk/icecast/src/auth.c	2007-11-08 19:52:51 UTC (rev 14114)
@@ -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 @@
 
     } 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 @@
 /* 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 @@
         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 @@
 
 /* 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 @@
 /* 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 @@
             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 @@
  * 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 @@
     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 @@
 
     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 @@
     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 @@
         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 @@
             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 @@
  */
 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 @@
             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 @@
             auth_user->mount = strdup (mount);
             auth_user->process = stream_end_callback;
 
-            queue_auth_client (auth_user);
+            queue_auth_client (auth_user, mountinfo);
         }
     }
 }

Modified: icecast/trunk/icecast/src/auth.h
===================================================================
--- icecast/trunk/icecast/src/auth.h	2007-11-08 13:57:27 UTC (rev 14113)
+++ icecast/trunk/icecast/src/auth.h	2007-11-08 19:52:51 UTC (rev 14114)
@@ -42,7 +42,7 @@
 {
     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;
 



More information about the commits mailing list