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

karl at svn.xiph.org karl at svn.xiph.org
Tue Aug 21 15:30:30 PDT 2007


Author: karl
Date: 2007-08-21 15:30:30 -0700 (Tue, 21 Aug 2007)
New Revision: 13583

Modified:
   icecast/trunk/icecast/src/auth.c
   icecast/trunk/icecast/src/auth.h
   icecast/trunk/icecast/src/auth_url.c
   icecast/trunk/icecast/src/cfgfile.c
   icecast/trunk/icecast/src/client.c
   icecast/trunk/icecast/src/connection.c
Log:
Auth update. Have each auth_t has its own queue of requests and thread to process
them. Each listener connection for each request is checked as connected before
performing the request (so that time isn't wasted on slow authentication). Various
name/comment cleanups as well.


Modified: icecast/trunk/icecast/src/auth.c
===================================================================
--- icecast/trunk/icecast/src/auth.c	2007-08-21 22:17:13 UTC (rev 13582)
+++ icecast/trunk/icecast/src/auth.c	2007-08-21 22:30:30 UTC (rev 13583)
@@ -37,11 +37,7 @@
 #define CATMODULE "auth"
 
 
-static volatile auth_client *clients_to_auth;
-static volatile unsigned int auth_pending_count;
-static volatile int auth_running;
 static mutex_t auth_lock;
-static thread_type *auth_thread;
 
 
 static void auth_client_setup (mount_proxy *mountinfo, client_t *client)
@@ -88,17 +84,25 @@
     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);
 }
 
 
 static void queue_auth_client (auth_client *auth_user)
 {
-    thread_mutex_lock (&auth_lock);
-    auth_user->next = (auth_client *)clients_to_auth;
-    clients_to_auth = auth_user;
-    auth_pending_count++;
-    thread_mutex_unlock (&auth_lock);
+    auth_t *auth;
+
+    if (auth_user == NULL)
+        return;
+    auth = auth_user->client->auth;
+    thread_mutex_lock (&auth->lock);
+    auth_user->next = NULL;
+    *auth->tailp = auth_user;
+    auth->tailp = &auth_user->next;
+    auth->pending_count++;
+    INFO2 ("auth on %s has %d pending", auth->mount, auth->pending_count);
+    thread_mutex_unlock (&auth->lock);
 }
 
 
@@ -112,22 +116,28 @@
 
     thread_mutex_lock (&authenticator->lock);
     authenticator->refcount--;
+    DEBUG2 ("...refcount on auth_t %s is now %d", authenticator->mount, authenticator->refcount);
     if (authenticator->refcount)
     {
         thread_mutex_unlock (&authenticator->lock);
         return;
     }
 
+    /* cleanup auth thread attached to this auth */
+    authenticator->running = 0;
+    thread_join (authenticator->thread);
+
     if (authenticator->free)
         authenticator->free (authenticator);
     xmlFree (authenticator->type);
     thread_mutex_unlock (&authenticator->lock);
     thread_mutex_destroy (&authenticator->lock);
+    free (authenticator->mount);
     free (authenticator);
 }
 
 
-void auth_client_free (auth_client *auth_user)
+static void auth_client_free (auth_client *auth_user)
 {
     if (auth_user == NULL)
         return;
@@ -146,6 +156,19 @@
 }
 
 
+/* verify that the listener is still connected. */
+static int is_listener_connected (client_t *client)
+{
+    int ret = 1;
+    if (client)
+    {
+        if (sock_active (client->con->sock) == 0)
+            ret = 0;
+    }
+    return ret;
+}
+
+
 /* wrapper function for auth thread to authenticate new listener
  * connection details
  */
@@ -153,50 +176,90 @@
 {
     client_t *client = auth_user->client;
 
+    /* make sure there is still a client at this point, a slow backend request
+     * can be avoided if client has disconnected */
+    if (is_listener_connected (client) == 0)
+    {
+        DEBUG0 ("listener is no longer connected");
+        client->respcode = 400;
+        return;
+    }
     if (client->auth->authenticate)
     {
         if (client->auth->authenticate (auth_user) != AUTH_OK)
-        {
-            auth_release (client->auth);
-            client->auth = NULL;
             return;
-        }
     }
-    if (auth_postprocess_client (auth_user) < 0)
+    if (auth_postprocess_listener (auth_user) < 0)
         INFO1 ("client %lu failed", client->con->id);
 }
 
 
-/* wrapper function are auth thread to authenticate new listener
- * connections
+/* wrapper function for auth thread to drop listener connections
  */
 static void auth_remove_listener (auth_client *auth_user)
 {
     client_t *client = auth_user->client;
 
-    if (client->auth->release_client)
-        client->auth->release_client (auth_user);
+    if (client->auth->release_listener)
+        client->auth->release_listener (auth_user);
     auth_release (client->auth);
     client->auth = NULL;
-    return;
+    /* client is going, so auth is not an issue at this point */
+    client->authenticated = 0;
 }
 
 
+/* 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)
+{
+    auth_t *auth = auth_user->client->auth;
+
+    if (auth->stream_start)
+        auth->stream_start (auth_user);
+}
+
+
+/* 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)
+{
+    auth_t *auth = auth_user->client->auth;
+
+    if (auth->stream_end)
+        auth->stream_end (auth_user);
+}
+
+
 /* The auth thread main loop. */
 static void *auth_run_thread (void *arg)
 {
+    auth_t *auth = arg;
+
     INFO0 ("Authentication thread started");
-    while (1)
+    while (auth->running)
     {
-        if (clients_to_auth)
+        /* usually no clients are waiting, so don't bother taking locks */
+        if (auth->head)
         {
             auth_client *auth_user;
 
-            thread_mutex_lock (&auth_lock);
-            auth_user = (auth_client*)clients_to_auth;
-            clients_to_auth = auth_user->next;
-            auth_pending_count--;
-            thread_mutex_unlock (&auth_lock);
+            /* may become NULL before lock taken */
+            thread_mutex_lock (&auth->lock);
+            auth_user = (auth_client*)auth->head;
+            if (auth_user == NULL)
+            {
+                thread_mutex_unlock (&auth->lock);
+                continue;
+            }
+            DEBUG2 ("%d client(s) pending on %s", auth->pending_count, auth->mount);
+            auth->head = auth_user->next;
+            if (auth->head == NULL)
+                auth->tailp = &auth->head;
+            auth->pending_count--;
+            thread_mutex_unlock (&auth->lock);
             auth_user->next = NULL;
 
             if (auth_user->process)
@@ -208,9 +271,6 @@
 
             continue;
         }
-        /* is there a request to shutdown */
-        if (auth_running == 0)
-            break;
         thread_sleep (150000);
     }
     INFO0 ("Authenication thread shutting down");
@@ -271,7 +331,7 @@
 /* if 0 is returned then the client should not be touched, however if -1
  * is returned then the caller is responsible for handling the client
  */
-static int add_client_to_source (source_t *source, client_t *client)
+static int add_listener_to_source (source_t *source, client_t *client)
 {
     int loop = 10;
     do
@@ -326,7 +386,7 @@
 /* Add listener to the pending lists of either the  source or fserve thread.
  * This can be run from the connection or auth thread context
  */
-static int add_authenticated_client (const char *mount, mount_proxy *mountinfo, client_t *client)
+static int add_authenticated_listener (const char *mount, mount_proxy *mountinfo, client_t *client)
 {
     int ret = 0;
     source_t *source = NULL;
@@ -348,7 +408,7 @@
                 client->con->discon_time = time(NULL) + mountinfo->max_listener_duration;
         }
 
-        ret = add_client_to_source (source, client);
+        ret = add_listener_to_source (source, client);
         avl_tree_unlock (global.source_tree);
         if (ret == 0)
             DEBUG0 ("client authenticated, passed to source");
@@ -362,15 +422,16 @@
 }
 
 
-int auth_postprocess_client (auth_client *auth_user)
+int auth_postprocess_listener (auth_client *auth_user)
 {
     int ret;
+    client_t *client = auth_user->client;
     ice_config_t *config = config_get_config();
 
     mount_proxy *mountinfo = config_find_mount (config, auth_user->mount);
-    auth_user->client->authenticated = 1;
+    client->authenticated = 1;
 
-    ret = add_authenticated_client (auth_user->mount, mountinfo, auth_user->client);
+    ret = add_authenticated_listener (auth_user->mount, mountinfo, client);
     config_release_config();
 
     if (ret < 0)
@@ -384,7 +445,7 @@
 /* Add a listener. Check for any mount information that states any
  * authentication to be used.
  */
-void add_client (const char *mount, client_t *client)
+void auth_add_listener (const char *mount, client_t *client)
 {
     mount_proxy *mountinfo; 
     ice_config_t *config = config_get_config();
@@ -400,7 +461,7 @@
     {
         auth_client *auth_user;
 
-        if (auth_pending_count > 30)
+        if (mountinfo->auth->pending_count > 100)
         {
             config_release_config ();
             WARN0 ("too many clients awaiting authentication");
@@ -410,11 +471,6 @@
         auth_client_setup (mountinfo, client);
         config_release_config ();
 
-        if (client->auth == NULL)
-        {
-            client_send_401 (client);
-            return;
-        }
         auth_user = calloc (1, sizeof (auth_client));
         if (auth_user == NULL)
         {
@@ -430,7 +486,7 @@
     }
     else
     {
-        int ret = add_authenticated_client (mount, mountinfo, client);
+        int ret = add_authenticated_listener (mount, mountinfo, client);
         config_release_config ();
         if (ret < 0)
             client_send_403 (client, "max listeners reached");
@@ -441,7 +497,7 @@
 /* determine whether we need to process this client further. This
  * involves any auth exit, typically for external auth servers.
  */
-int release_client (client_t *client)
+int auth_release_listener (client_t *client)
 {
     if (client->auth)
     {
@@ -465,13 +521,16 @@
     do
     {
         DEBUG1 ("type is %s", auth->type);
-#ifdef HAVE_AUTH_URL
+
         if (strcmp (auth->type, "url") == 0)
         {
+#ifdef HAVE_AUTH_URL
             auth_get_url_auth (auth, options);
+#else
+            ERROR0 ("Auth URL disabled");
+#endif
             break;
         }
-#endif
         if (strcmp (auth->type, "htpasswd") == 0)
         {
             auth_get_htpasswd_auth (auth, options);
@@ -531,7 +590,12 @@
     }
     auth->type = xmlGetProp (node, "type");
     get_authenticator (auth, options);
+    auth->tailp = &auth->head;
     thread_mutex_create (&auth->lock);
+
+    auth->running = 1;
+    auth->thread = thread_create ("auth thread", auth_run_thread, auth, THREAD_ATTACHED);
+
     while (options)
     {
         config_options_t *opt = options;
@@ -555,7 +619,7 @@
         if (auth_user)
         {
             auth_user->mount = strdup (mount);
-            auth_user->process = mountinfo->auth->stream_start;
+            auth_user->process = stream_start_callback;
 
             queue_auth_client (auth_user);
         }
@@ -574,7 +638,7 @@
         if (auth_user)
         {
             auth_user->mount = strdup (mount);
-            auth_user->process = mountinfo->auth->stream_end;
+            auth_user->process = stream_end_callback;
 
             queue_auth_client (auth_user);
         }
@@ -586,20 +650,12 @@
 
 void auth_initialise (void)
 {
-    clients_to_auth = NULL;
-    auth_pending_count = 0;
-    auth_running = 1;
     thread_mutex_create (&auth_lock);
-    auth_thread = thread_create ("auth thread", auth_run_thread, NULL, THREAD_ATTACHED);
 }
 
 void auth_shutdown (void)
 {
-    if (auth_thread)
-    {
-        auth_running = 0;
-        thread_join (auth_thread);
-        INFO0 ("Auth thread has terminated");
-    }
+    thread_mutex_destroy (&auth_lock);
+    INFO0 ("Auth shutdown");
 }
 

Modified: icecast/trunk/icecast/src/auth.h
===================================================================
--- icecast/trunk/icecast/src/auth.h	2007-08-21 22:17:13 UTC (rev 13582)
+++ icecast/trunk/icecast/src/auth.h	2007-08-21 22:30:30 UTC (rev 13583)
@@ -53,29 +53,38 @@
 
     /* Authenticate using the given username and password */
     auth_result (*authenticate)(auth_client *aclient);
-    auth_result (*release_client)(auth_client *auth_user);
+    auth_result (*release_listener)(auth_client *auth_user);
 
-    /* callbacks to specific auth for notifying auth server on source
-     * startup or shutdown
-     */
+    /* auth handler for source startup, no client passed as it may disappear */
     void (*stream_start)(auth_client *auth_user);
+
+    /* auth handler for source exit, no client passed as it may disappear */
     void (*stream_end)(auth_client *auth_user);
 
+    /* auth state-specific free call */
     void (*free)(struct auth_tag *self);
+
     auth_result (*adduser)(struct auth_tag *auth, const char *username, const char *password);
     auth_result (*deleteuser)(struct auth_tag *auth, const char *username);
     auth_result (*listuser)(struct auth_tag *auth, xmlNodePtr srcnode);
 
     mutex_t lock;
+    int running;
     int refcount;
     int allow_duplicate_users;
 
+    thread_type *thread;
+
+    /* per-auth queue for clients */
+    auth_client *head, **tailp;
+    int pending_count;
+
     void *state;
     char *type;
 } auth_t;
 
-void add_client (const char *mount, client_t *client);
-int  release_client (client_t *client);
+void auth_add_listener (const char *mount, client_t *client);
+int  auth_release_listener (client_t *client);
 
 void auth_initialise (void);
 void auth_shutdown (void);
@@ -91,7 +100,7 @@
 
 /* called from auth thread, after the client has successfully authenticated
  * and requires adding to source or fserve. */
-int auth_postprocess_client (auth_client *auth_user);
+int auth_postprocess_listener (auth_client *auth_user);
 
 #endif
 

Modified: icecast/trunk/icecast/src/auth_url.c
===================================================================
--- icecast/trunk/icecast/src/auth_url.c	2007-08-21 22:17:13 UTC (rev 13582)
+++ icecast/trunk/icecast/src/auth_url.c	2007-08-21 22:30:30 UTC (rev 13583)
@@ -162,7 +162,7 @@
 }
 
 
-static auth_result url_remove_client (auth_client *auth_user)
+static auth_result url_remove_listener (auth_client *auth_user)
 {
     client_t *client = auth_user->client;
     auth_t *auth = client->auth;
@@ -242,7 +242,7 @@
 }
 
 
-static auth_result url_add_client (auth_client *auth_user)
+static auth_result url_add_listener (auth_client *auth_user)
 {
     client_t *client = auth_user->client;
     auth_t *auth = client->auth;
@@ -463,8 +463,8 @@
 {
     auth_url *url_info;
 
-    authenticator->authenticate = url_add_client;
-    authenticator->release_client = url_remove_client;
+    authenticator->authenticate = url_add_listener;
+    authenticator->release_listener = url_remove_listener;
 
     authenticator->free = auth_url_clear;
     authenticator->adduser = auth_url_adduser;

Modified: icecast/trunk/icecast/src/cfgfile.c
===================================================================
--- icecast/trunk/icecast/src/cfgfile.c	2007-08-21 22:17:13 UTC (rev 13582)
+++ icecast/trunk/icecast/src/cfgfile.c	2007-08-21 22:30:30 UTC (rev 13583)
@@ -675,6 +675,8 @@
         config_clear_mount (mount);
         return;
     }
+    if (mount->auth)
+        mount->auth->mount = strdup (mount->mountname);
     while(current) {
         last = current;
         current = current->next;

Modified: icecast/trunk/icecast/src/client.c
===================================================================
--- icecast/trunk/icecast/src/client.c	2007-08-21 22:17:13 UTC (rev 13582)
+++ icecast/trunk/icecast/src/client.c	2007-08-21 22:30:30 UTC (rev 13583)
@@ -93,7 +93,7 @@
         client->refbuf = NULL;
     }
 
-    if (release_client (client))
+    if (auth_release_listener (client))
         return;
 
     /* write log entry if ip is set (some things don't set it, like outgoing 

Modified: icecast/trunk/icecast/src/connection.c
===================================================================
--- icecast/trunk/icecast/src/connection.c	2007-08-21 22:17:13 UTC (rev 13582)
+++ icecast/trunk/icecast/src/connection.c	2007-08-21 22:30:30 UTC (rev 13583)
@@ -882,7 +882,7 @@
         return;
     }
 
-    add_client (uri, client);
+    auth_add_listener (uri, client);
     if (uri != passed_uri) free (uri);
 }
 



More information about the commits mailing list