[xiph-commits] r9111 - icecast/branches/kh/icecast/src

karl at motherfish-iii.xiph.org karl at motherfish-iii.xiph.org
Mon Apr 4 19:10:10 PDT 2005


Author: karl
Date: 2005-04-04 19:09:58 -0700 (Mon, 04 Apr 2005)
New Revision: 9111

Modified:
   icecast/branches/kh/icecast/src/admin.c
   icecast/branches/kh/icecast/src/auth.c
   icecast/branches/kh/icecast/src/auth.h
   icecast/branches/kh/icecast/src/auth_cmd.c
   icecast/branches/kh/icecast/src/auth_cmd.h
   icecast/branches/kh/icecast/src/auth_htpasswd.c
   icecast/branches/kh/icecast/src/auth_htpasswd.h
   icecast/branches/kh/icecast/src/auth_url.c
   icecast/branches/kh/icecast/src/auth_url.h
   icecast/branches/kh/icecast/src/cfgfile.c
   icecast/branches/kh/icecast/src/cfgfile.h
   icecast/branches/kh/icecast/src/client.c
   icecast/branches/kh/icecast/src/client.h
   icecast/branches/kh/icecast/src/connection.c
   icecast/branches/kh/icecast/src/fserve.c
   icecast/branches/kh/icecast/src/fserve.h
   icecast/branches/kh/icecast/src/main.c
   icecast/branches/kh/icecast/src/source.c
   icecast/branches/kh/icecast/src/source.h
   icecast/branches/kh/icecast/src/util.c
   icecast/branches/kh/icecast/src/util.h
Log:
auth update. moved authenticator to mount structure allowing mount
to apply to files in webroot as well as to streams. simplify the auth
thread handler, in extreme cases the previous version could have
scaling problems.


Modified: icecast/branches/kh/icecast/src/admin.c
===================================================================
--- icecast/branches/kh/icecast/src/admin.c	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/admin.c	2005-04-05 02:09:58 UTC (rev 9111)
@@ -250,16 +250,23 @@
             xmlNewChild (srcnode, NULL, "listeners", buf);
             if (source->running)
             {
+                ice_config_t *config;
+                mount_proxy *mountinfo;
+
                 snprintf (buf, sizeof(buf), "%lu",
                         (unsigned long)(now - source->con->con_time));
                 xmlNewChild (srcnode, NULL, "Connected", buf);
                 xmlNewChild (srcnode, NULL, "content-type", 
                         source->format->contenttype);
-                if (source->authenticator)
+
+                config = config_get_config();
+                mountinfo = config_find_mount (config, source->mount);
+                if (mountinfo->auth)
                 {
                     xmlNewChild(srcnode, NULL, "authenticator", 
-                            source->authenticator->type);
+                            mountinfo->auth->type);
                 }
+                config_release_config();
             }
         }
         thread_mutex_unlock (&source->lock);
@@ -787,12 +794,23 @@
     char *password = NULL;
     char *message = NULL;
     int ret = AUTH_OK;
+    mount_proxy *mountinfo = NULL;
 
-    if((COMMAND_OPTIONAL(client, "action", action))) {
+    if((COMMAND_OPTIONAL(client, "action", action)))
+    {
+        ice_config_t *config = config_get_config ();
+        mountinfo = config_find_mount (config, source->mount);
+        if (mountinfo == NULL || mountinfo->auth == NULL)
+        {
+            WARN1 ("manage auth request for %s but no facility available", source->mount);
+            config_release_config ();
+            client_send_404 (client, "no such auth facility");
+            return;
+        }
         if (!strcmp(action, "add")) {
             COMMAND_REQUIRE(client, "username", username);
             COMMAND_REQUIRE(client, "password", password);
-            ret = source->authenticator->adduser(source->authenticator, username, password);
+            ret = mountinfo->auth->adduser(mountinfo->auth, username, password);
             if (ret == AUTH_FAILED) {
                 message = strdup("User add failed - check the icecast error log");
             }
@@ -805,7 +823,7 @@
         }
         if (!strcmp(action, "delete")) {
             COMMAND_REQUIRE(client, "username", username);
-            ret = source->authenticator->deleteuser(source->authenticator, username);
+            ret = mountinfo->auth->deleteuser(mountinfo->auth, username);
             if (ret == AUTH_FAILED) {
                 message = strdup("User delete failed - check the icecast error log");
             }
@@ -813,6 +831,7 @@
                 message = strdup("User deleted");
             }
         }
+        config_release_config ();
     }
 
     doc = xmlNewDoc("1.0");
@@ -827,7 +846,8 @@
 
     xmlDocSetRootElement(doc, node);
 
-    source->authenticator->listuser(source->authenticator, srcnode);
+    if (mountinfo && mountinfo->auth && mountinfo->auth->listuser)
+        mountinfo->auth->listuser (mountinfo->auth, srcnode);
 
     admin_send_response(doc, client, response, 
             MANAGEAUTH_TRANSFORMED_REQUEST);

Modified: icecast/branches/kh/icecast/src/auth.c
===================================================================
--- icecast/branches/kh/icecast/src/auth.c	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/auth.c	2005-04-05 02:09:58 UTC (rev 9111)
@@ -32,176 +32,149 @@
 #include "cfgfile.h"
 #include "stats.h"
 #include "httpp/httpp.h"
-#include "md5.h"
+#include "fserve.h"
 
 #include "logging.h"
 #define CATMODULE "auth"
 
 
+volatile static auth_client *clients_to_auth;
+volatile static int auth_running;
+static mutex_t auth_lock;
+static thread_type *auth_thread;
 
-auth_result auth_check_client(source_t *source, client_t *client)
+
+static void auth_client_setup (mount_proxy *mountinfo, client_t *client)
 {
-    auth_t *authenticator = source->authenticator;
-    auth_result result;
+    /* This will look something like "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" */
+    char *header = httpp_getvar(client->parser, "authorization");
+    char *userpass, *tmp;
+    char *username, *password;
+    auth_client *auth_user;
 
-    if (client->is_slave == 0 && authenticator) {
-        /* This will look something like "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" */
-        char *header = httpp_getvar(client->parser, "authorization");
-        char *userpass, *tmp;
-        char *username, *password;
+    if (header == NULL || strncmp(header, "Basic ", 6))
+    {
+        INFO0("Authorization not using Basic");
+        return;
+    }
 
-        if(header == NULL)
-            return AUTH_FAILED;
+    userpass = util_base64_decode (header+6);
+    if (userpass == NULL)
+    {
+        WARN1("Base64 decode of Authorization header \"%s\" failed",
+                header+6);
+        return;
+    }
 
-        if(strncmp(header, "Basic ", 6)) {
-            INFO0("Authorization not using Basic");
-            return 0;
-        }
+    tmp = strchr(userpass, ':');
+    if (tmp == NULL)
+    { 
+        free (auth_user);
+        free (userpass);
+        return;
+    }
 
-        userpass = util_base64_decode(header+6);
-        if(userpass == NULL) {
-            WARN1("Base64 decode of Authorization header \"%s\" failed",
-                    header+6);
-            return AUTH_FAILED;
-        }
+    *tmp = 0;
+    username = userpass;
+    password = tmp+1;
 
-        tmp = strchr(userpass, ':');
-        if(!tmp) { 
-            free(userpass);
-            return AUTH_FAILED;
-        }
+    client->auth = mountinfo->auth;
+    client->auth->refcount++;
+    client->username = strdup (username);
+    client->password = strdup (password);
 
-        *tmp = 0;
-        username = userpass;
-        password = tmp+1;
+    free(userpass);
+}
 
-        client->username = strdup (username);
-        client->password = strdup (password);
 
-        result = authenticator->authenticate (source, client);
-
-        free(userpass);
-
-        return result;
-    }
-    else
-    {
-        /* just add the client, this shouldn't fail */
-        add_authenticated_client (source, client);
-        return AUTH_OK;
-    }
+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;
+    thread_mutex_unlock (&auth_lock);
 }
 
 
-void auth_clear(auth_t *authenticator)
+/* release the auth. It is referred to by multiple structures so this is
+ * refcounted and only actual freed after the last use
+ */
+void auth_release (auth_t *authenticator)
 {
     if (authenticator == NULL)
         return;
-    authenticator->free (authenticator);
+
+    authenticator->refcount--;
+    if (authenticator->refcount)
+        return;
+
+    if (authenticator->free)
+        authenticator->free (authenticator);
     free (authenticator->type);
     free (authenticator);
 }
 
 
-auth_t *auth_get_authenticator(const char *type, config_options_t *options)
+void auth_client_free (auth_client *auth_user)
 {
-    auth_t *auth = NULL;
-#ifdef HAVE_AUTH_URL
-    if(!strcmp(type, "url")) {
-        auth = auth_get_url_auth(options);
-        auth->type = strdup(type);
-    }
-    else
-#endif
-    if(!strcmp(type, "command")) {
-#ifdef WIN32
-        ERROR1("Authenticator type: \"%s\" not supported on win32 platform", type);
-        return NULL;
-#else
-        auth = auth_get_cmd_auth(options);
-        auth->type = strdup(type);
-#endif
-    }
-    else if(!strcmp(type, "htpasswd")) {
-        auth = auth_get_htpasswd_auth(options);
-        auth->type = strdup(type);
-    }
-    else {
-        ERROR1("Unrecognised authenticator type: \"%s\"", type);
-        return NULL;
-    }
+    if (auth_user == NULL)
+        return;
+    if (auth_user->client)
+    {
+        client_t *client = auth_user->client;
 
-    if (auth)
-    {
-        while (options)
-        {
-            if (!strcmp(options->name, "allow_duplicate_users"))
-                auth->allow_duplicate_users = atoi(options->value);
-            options = options->next;
-        }
-        return auth;
+        /* failed client, drop global count */
+        global_lock();
+        global.clients--;
+        global_unlock();
+        if (client->respcode)
+            client_destroy (client);
+        else
+            client_send_401 (client);
+        auth_user->client = NULL;
     }
-    ERROR1("Couldn't configure authenticator of type \"%s\"", type);
-    return NULL;
+    free (auth_user);
 }
 
 
-/* This should be called after auth has completed. After the user has
- * been authenticated the client is ready to be placed on the source, but
- * may still be dropped.
- * Don't use client after this call, however a return of 0 indicates that
- * client is on the source whereas -1 means that the client has failed
- */
-int auth_postprocess_client (const char *mount, client_t *client)
+/* The auth thread main loop. */
+static void *auth_run_thread (void *arg)
 {
-    int ret = -1;
-    source_t *source;
-    avl_tree_rlock (global.source_tree);
-    source = source_find_mount (mount);
-    if (source)
+    INFO0 ("Authenication thread started");
+    while (1)
     {
-        thread_mutex_lock (&source->lock);
+        if (clients_to_auth)
+        {
+            auth_client *auth_user;
 
-        if (source->running || source->on_demand)
-            ret = add_authenticated_client (source, client);
+            thread_mutex_lock (&auth_lock);
+            auth_user = (auth_client*)clients_to_auth;
+            clients_to_auth = auth_user->next;
+            thread_mutex_unlock (&auth_lock);
+            auth_user->next = NULL;
 
-        thread_mutex_unlock (&source->lock);
-    }
-    avl_tree_unlock (global.source_tree);
-    return ret;
-}
+            if (auth_user->process == NULL)
+                ERROR0 ("client auth process not set");
 
+            if (auth_user->process (auth_user) != AUTH_OK)
+            {
+                INFO0 ("client failed");
+            }
 
-void auth_failed_client (const char *mount)
-{
-    source_t *source;
+            auth_client_free (auth_user);
 
-    avl_tree_rlock (global.source_tree);
-    source = source_find_mount (mount);
-    if (source)
-    {
-        thread_mutex_lock (&source->lock);
-
-        if (source->new_listeners)
-            source->new_listeners--;
-
-        thread_mutex_unlock (&source->lock);
+            continue;
+        }
+        /* is there a request to shutdown */
+        if (auth_running == 0)
+            break;
+        thread_sleep (150000);
     }
-    avl_tree_unlock (global.source_tree);
+    INFO0 ("Authenication thread shutting down");
+    return NULL;
 }
 
 
-void auth_close_client (client_t *client)
-{
-    /* failed client, drop global count */
-    global_lock();
-    global.clients--;
-    global_unlock();
-    if (client->respcode)
-        client_destroy (client);
-    else
-        client_send_401 (client);
-}
 
 
 /* Check whether this client is currently on this mount, the client may be
@@ -210,7 +183,7 @@
  */
 static int check_duplicate_logins (source_t *source, client_t *client)
 {
-    auth_t *auth = source->authenticator;
+    auth_t *auth = client->auth;
 
     /* allow multiple authenticated relays */
     if (client->username == NULL || client->is_slave)
@@ -243,13 +216,42 @@
  * 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
  */
-int add_authenticated_client (source_t *source, client_t *client)
+int add_client_to_source (source_t *source, client_t *client)
 {
-    if (source->authenticator && check_duplicate_logins (source, client) == 0)
+    int loop = 10;
+    do
+    {
+        unsigned int total;
+        thread_mutex_lock (&source->lock);
+        total = source->new_listeners + source->listeners;
+        DEBUG2 ("max on %s is %d", source->mount, source->max_listeners);
+        DEBUG2 ("pending %d, current %d", source->new_listeners, source->listeners);
+        if (source->max_listeners == -1)
+            break;
+        if (client->is_slave)
+            break;
+        if (total < (unsigned int)source->max_listeners)
+            break;
+
+        if (loop && source->fallback_when_full && source->fallback_mount)
+        {
+            source_t *next = source_find_mount (source->fallback_mount);
+            thread_mutex_unlock (&source->lock);
+            INFO1 ("stream full trying %s", next->mount);
+            source = next;
+            loop--;
+            continue;
+        }
+        /* now we fail the client */
+        thread_mutex_unlock (&source->lock);
         return -1;
+
+    } while (1);
     /* lets add the client to the pending list */
+    source->new_listeners++;
     client->next = source->pending_clients;
     source->pending_clients = client;
+    thread_mutex_unlock (&source->lock);
 
     client->write_to_client = format_http_write_to_client;
     client->refbuf = refbuf_new (4096);
@@ -269,107 +271,230 @@
 }
 
 
-/* try to add client to a pending list.  return
- *  0 for success
- *  -1 too many clients
- *  -2 mount needs authentication
- *  -3 mount is unavailable
+/* 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_client (char *passed_mount, client_t *client, int initial_connection)
+static int add_authenticated_client (const char *mount, mount_proxy *mountinfo, client_t *client)
 {
-    source_t *source;
-    char *mount = passed_mount;
-    
-    while (1)
+    int ret = 0;
+    source_t *source = NULL;
+
+    avl_tree_rlock (global.source_tree);
+    source = source_find_mount (mount);
+
+    if (source)
     {
-        source = source_find_mount (mount);
-        if (passed_mount != mount) 
-            free (mount);
-        if (source == NULL)
-            return -3;
-        if (initial_connection && source->no_mount
-                && strcmp (source->mount, passed_mount) == 0)
-            return -3;
-        thread_mutex_lock (&source->lock);
-
-        if (source->running || source->on_demand)
+        if (client->auth && check_duplicate_logins (source, client) == 0)
         {
-            DEBUG2 ("max on %s is %d", source->mount, source->max_listeners);
-            DEBUG2 ("pending %d, current %d", source->new_listeners, source->listeners);
-            if (source->max_listeners == -1)
-                break;
-            if (client->is_slave)
-                break;
-            if (source->new_listeners + source->listeners < (unsigned int)source->max_listeners)
-                break;
-
-            INFO2 ("max listeners (%d) reached on %s", source->max_listeners, source->mount);
-            if (source->fallback_when_full == 0 || source->fallback_mount == NULL)
-            {
-                thread_mutex_unlock (&source->lock);
-                return -1;
-            }
-            if (source->fallback_mount)
-                mount = strdup (source->fallback_mount);
-            else
-                mount = NULL;
+            avl_tree_unlock (global.source_tree);
+            return -1;
         }
-
-        thread_mutex_unlock (&source->lock);
+        ret = add_client_to_source (source, client);
+        avl_tree_unlock (global.source_tree);
+        DEBUG0 ("client authenticated, passed to source");
     }
-
-    if (auth_check_client (source, client) != AUTH_OK)
+    else
     {
-        thread_mutex_unlock (&source->lock);
-        INFO0 ("listener failed to authenticate");
-        return -2;
+        avl_tree_unlock (global.source_tree);
+        ret = fserve_client_create (client, mount);
     }
-    source->new_listeners++;
+    return ret;
+}
 
-    thread_mutex_unlock (&source->lock);
-    return 0;
+
+int auth_postprocess_client (auth_client *auth_user)
+{
+    int ret;
+    ice_config_t *config = config_get_config();
+
+    mount_proxy *mountinfo = config_find_mount (config, auth_user->mount);
+    auth_user->client->authenticated = 1;
+
+    ret = add_authenticated_client (auth_user->mount, mountinfo, auth_user->client);
+    config_release_config();
+
+    if (ret < 0)
+        client_send_504 (auth_user->client, "stream full");
+    auth_user->client = NULL;
+
+    return ret;
 }
 
 
-void add_client (char *mount, client_t *client)
+/* Add a listener. Check for any mount information that states any
+ * authentication to be used.
+ */
+void add_client (const char *mount, client_t *client)
 {
-    int added = -3;
+    mount_proxy *mountinfo; 
+    ice_config_t *config = config_get_config();
 
-    if (mount)
+    mountinfo = config_find_mount (config, mount);
+    if (mountinfo && mountinfo->auth)
     {
+        auth_client *auth_user;
+
+        auth_client_setup (mountinfo, client);
+        config_release_config ();
+
+        /* config lock taken in here */
         if (connection_check_relay_pass(client->parser))
         {
             client_as_slave (client);
             INFO0 ("client connected as slave");
         }
-        thread_mutex_lock (&move_clients_mutex);
-        avl_tree_rlock (global.source_tree);
-        added = _add_client (mount, client, 1);
-        avl_tree_unlock (global.source_tree);
-        thread_mutex_unlock (&move_clients_mutex);
+        auth_user = calloc (1, sizeof (auth_client));
+        if (auth_user == NULL || client->auth == NULL)
+        {
+            client_send_401 (client);
+            return;
+        }
+        auth_user->mount = strdup (mount);
+        auth_user->process = client->auth->authenticate;
+        auth_user->client = client;
+
+        queue_auth_client (auth_user);
     }
-    switch (added)
+    else
     {
-    case -1: 
-        /* there may be slaves we can re-direct to */
-        if (slave_redirect (mount, client))
+        int ret = add_authenticated_client (mount, mountinfo, client);
+        config_release_config ();
+        if (ret < 0)
+            client_send_504 (client, "stream_full");
+    }
+}
+
+
+/* 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)
+{
+    if (client->auth && client->auth->release_client)
+    {
+        auth_client *auth_user = calloc (1, sizeof (auth_client));
+        if (auth_user == NULL)
+            return 0;
+
+        auth_user->mount = strdup (httpp_getvar (client->parser, HTTPP_VAR_URI));
+        auth_user->process = client->auth->release_client;
+        auth_user->client = client;
+
+        queue_auth_client (auth_user);
+        return 1;
+    }
+    return 0;
+}
+
+
+static void get_authenticator (auth_t *auth, config_options_t *options)
+{
+    do
+    {
+#ifdef HAVE_AUTH_URL
+        if (strcmp (auth->type, "url") == 0)
+        {
+            auth_get_url_auth (auth, options);
             break;
-        client_send_404 (client,
-                "Too many clients on this mountpoint. Try again later.");
-        DEBUG1 ("max clients on %s", mount);
-        break;
-    case -2:
-        client_send_401 (client);
-        break;
-    case -3:
-        client_send_404 (client, "The file you requested could not be found");
-        break;
-    default:
+        }
+#endif
+        if (strcmp (auth->type, "command") == 0)
+        {
+#ifdef WIN32
+            ERROR1("Authenticator type: \"%s\" not supported on win32 platform", type);
+            return NULL;
+#else
+            auth_get_cmd_auth (auth, options);
+            break;
+#endif
+        }
+        if (strcmp (auth->type, "htpasswd") == 0)
+        {
+            auth_get_htpasswd_auth (auth, options);
+            break;
+        }
+        
+        ERROR1("Unrecognised authenticator type: \"%s\"", auth->type);
         return;
+    } while (0);
+
+    auth->refcount = 1;
+    while (options)
+    {
+        if (strcmp(options->name, "allow_duplicate_users") == 0)
+            auth->allow_duplicate_users = atoi (options->value);
+        options = options->next;
     }
-    /* failed client, drop global count */
-    global_lock();
-    global.clients--;
-    global_unlock();
 }
 
+
+auth_t *auth_get_authenticator (xmlNodePtr node)
+{
+    auth_t *auth = calloc (1, sizeof (auth_t));
+    config_options_t *options = NULL, **next_option = &options;
+    xmlNodePtr option;
+
+    if (auth == NULL)
+        return NULL;
+
+    option = node->xmlChildrenNode;
+    while (option)
+    {
+        xmlNodePtr current = option;
+        option = option->next;
+        if (strcmp (current->name, "option") == 0)
+        {
+            config_options_t *opt = calloc (1, sizeof (config_options_t));
+            opt->name = xmlGetProp (current, "name");
+            if (opt->name == NULL)
+            {
+                free(opt);
+                continue;
+            }
+            opt->value = xmlGetProp (current, "value");
+            if (opt->value == NULL)
+            {
+                xmlFree (opt->name);
+                free (opt);
+                continue;
+            }
+            *next_option = opt;
+            next_option = &opt->next;
+        }
+        else
+            WARN1 ("unknown auth setting (%s)", current->name);
+    }
+    auth->type = xmlGetProp (node, "type");
+    get_authenticator (auth, options);
+    while (options)
+    {
+        config_options_t *opt = options;
+        options = opt->next;
+        xmlFree (opt->name);
+        xmlFree (opt->value);
+        free (opt);
+    }
+    return auth;
+}
+
+
+/* these are called at server start and termination */
+
+void auth_initialise ()
+{
+    clients_to_auth = NULL;
+    auth_running = 1;
+    thread_mutex_create ("auth lock", &auth_lock);
+    auth_thread = thread_create ("auth thread", auth_run_thread, NULL, THREAD_ATTACHED);
+}
+
+void auth_shutdown ()
+{
+    if (auth_thread)
+    {
+        auth_running = 0;
+        thread_join (auth_thread);
+        INFO0 ("Auth thread has terminated");
+    }
+}
+

Modified: icecast/branches/kh/icecast/src/auth.h
===================================================================
--- icecast/branches/kh/icecast/src/auth.h	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/auth.h	2005-04-05 02:09:58 UTC (rev 9111)
@@ -17,14 +17,19 @@
 #include <config.h>
 #endif
 
+struct source_tag;
+struct auth_tag;
+
 #include <libxml/xmlmemory.h>
 #include <libxml/parser.h>
 #include <libxml/tree.h>
-#include "source.h"
+#include "cfgfile.h"
 #include "client.h"
+#include "thread/thread.h"
 
 typedef enum
 {
+    AUTH_UNDEFINED,
     AUTH_OK,
     AUTH_FAILED,
     AUTH_USERADDED,
@@ -32,33 +37,45 @@
     AUTH_USERDELETED,
 } auth_result;
 
+typedef struct auth_client_tag
+{
+    char        *mount;
+    client_t    *client;
+    auth_result (*process)(struct auth_client_tag *auth_user);
+    struct auth_client_tag *next;
+} auth_client;
+
+
 typedef struct auth_tag
 {
+    char *mount;
+
     /* Authenticate using the given username and password */
-    auth_result (*authenticate)(source_t *source, client_t *client);
+    auth_result (*authenticate)(auth_client *aclient);
+    auth_result (*release_client)(auth_client *auth_user);
+
     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);
-    void (*release_client)(struct source_tag *source, client_t *client);
-    int (*checkuser)(source_t *source, client_t *client);
+    int (*checkuser)(struct source_tag *source, client_t *client);
 
+    int refcount;
     int allow_duplicate_users;
 
     void *state;
     void *type;
 } auth_t;
 
-auth_result auth_check_client(source_t *source, client_t *client);
+void add_client (const char *mount, client_t *client);
+int  release_client (client_t *client);
 
-auth_t *auth_get_authenticator(const char *type, config_options_t *options);
-void auth_clear(auth_t *authenticator);
-int auth_postprocess_client (const char *mount, client_t *client);
-void auth_close_client (client_t *client);
-int add_authenticated_client (source_t *source, client_t *client);
-void auth_failed_client (const char *mount);
-void add_client (char *mount, client_t *client);
+void auth_initialise ();
+auth_t  *auth_get_authenticator (xmlNodePtr node);
+void    auth_release (auth_t *authenticator);
 
+int auth_postprocess_client (auth_client *auth_user);
+
 #endif
 
 

Modified: icecast/branches/kh/icecast/src/auth_cmd.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_cmd.c	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/auth_cmd.c	2005-04-05 02:09:58 UTC (rev 9111)
@@ -46,13 +46,6 @@
     char *filename;
 } auth_cmd;
 
-typedef struct {
-   char *mount;
-   client_t *client;
-   char *cmd;
-} auth_client;
-
-
 static void cmd_clear(auth_t *self)
 {
     auth_cmd *cmd = self->state;
@@ -60,18 +53,16 @@
     free(cmd);
 }
 
-static void *auth_cmd_thread (void *arg)
+static auth_result auth_cmd_client (auth_client *auth_user)
 {
-    auth_client *auth_user = arg;
     int fd[2];
-    int ok = 0;
-    int send_fail = 404;
     pid_t pid;
     client_t *client = auth_user->client;
+    auth_t *auth = client->auth;
+    auth_cmd *cmd = auth->state;
     int status, len;
     char str[512];
 
-    DEBUG0("starting auth thread");
     if (pipe (fd) == 0)
     {
         pid = fork();
@@ -81,7 +72,7 @@
                 dup2 (fd[0], fileno(stdin));
                 close (fd[0]);
                 close (fd[1]);
-                execl (auth_user->cmd, auth_user->cmd, NULL);
+                execl (cmd->filename, cmd->filename, NULL);
                 exit (EXIT_FAILURE);
             case -1:
                 break;
@@ -101,47 +92,15 @@
                 {
                     DEBUG1("command exited normally with %d", WEXITSTATUS (status));
                     if (WEXITSTATUS(status) == 0)
-                        ok = 1;
-                    else
-                        send_fail = 401;
+                        if (auth_postprocess_client (auth_user) < 0)
+                            return AUTH_FAILED;
                 }
                 break;
         }
-        /* try to add authenticated client */
-        if (ok)
-        {
-            auth_postprocess_client (auth_user->mount, auth_user->client);
-            send_fail = 0;
-        }
-        else
-            auth_failed_client (auth_user->mount);
     }
-    if (send_fail == 404)
-        client_send_404 (client, "Mount not available");
-    if (send_fail == 401)
-        client_send_401 (client);
-    free (auth_user->mount);
-    free (auth_user->cmd);
-    free (auth_user);
-    return NULL;
+    return AUTH_FAILED;
 }
 
-
-static auth_result auth_cmd_client (source_t *source, client_t *client)
-{
-    auth_client *auth_user = calloc (1, sizeof (auth_client));
-    auth_cmd *cmd = source->authenticator->state;
-
-    if (auth_user == NULL)
-        return AUTH_FAILED;
-
-    auth_user->cmd = strdup (cmd->filename);
-    auth_user->mount = strdup (source->mount);
-    auth_user->client = client;
-    thread_create("Auth by command thread", auth_cmd_thread, auth_user, THREAD_DETACHED);
-    return AUTH_OK;
-}
-
 static auth_result auth_cmd_adduser(auth_t *auth, const char *username, const char *password)
 {
     return AUTH_FAILED;
@@ -157,9 +116,8 @@
     return AUTH_FAILED;
 }
 
-auth_t *auth_get_cmd_auth (config_options_t *options)
+void auth_get_cmd_auth (auth_t *authenticator, config_options_t *options)
 {
-    auth_t *authenticator = calloc(1, sizeof(auth_t));
     auth_cmd *state;
 
     authenticator->authenticate = auth_cmd_client;
@@ -177,6 +135,5 @@
     }
     authenticator->state = state;
     INFO0("external command based authentication setup");
-    return authenticator;
 }
 

Modified: icecast/branches/kh/icecast/src/auth_cmd.h
===================================================================
--- icecast/branches/kh/icecast/src/auth_cmd.h	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/auth_cmd.h	2005-04-05 02:09:58 UTC (rev 9111)
@@ -17,7 +17,7 @@
 #include <config.h>
 #endif
 
-auth_t *auth_get_cmd_auth (config_options_t *options);
+void auth_get_cmd_auth (auth_t *, config_options_t *options);
 
 #endif
 

Modified: icecast/branches/kh/icecast/src/auth_htpasswd.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_htpasswd.c	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/auth_htpasswd.c	2005-04-05 02:09:58 UTC (rev 9111)
@@ -81,10 +81,11 @@
 #define MAX_LINE_LEN 512
 
 /* Not efficient; opens and scans the entire file for every request */
-static auth_result htpasswd_auth(source_t *source, client_t *client)
+static auth_result htpasswd_auth (auth_client *auth_user)
 {
-    auth_t *auth = source->authenticator;
+    auth_t *auth = auth_user->client->auth;
     htpasswd_auth_state *state = auth->state;
+    client_t *client = auth_user->client;
     FILE *passwdfile = fopen(state->filename, "rb");
     char line[MAX_LINE_LEN];
     char *sep;
@@ -116,7 +117,7 @@
                 fclose(passwdfile);
                 free(hashed_password);
                 thread_rwlock_unlock(&state->file_rwlock);
-                if (add_authenticated_client (source, client) < 0)
+                if (auth_postprocess_client (auth_user) < 0)
                     return AUTH_FAILED;
                 return AUTH_OK;
             }
@@ -132,9 +133,8 @@
     return AUTH_FAILED;
 }
 
-auth_t *auth_get_htpasswd_auth(config_options_t *options)
+int  auth_get_htpasswd_auth (auth_t *authenticator, config_options_t *options)
 {
-    auth_t *authenticator = calloc(1, sizeof(auth_t));
     htpasswd_auth_state *state;
 
     authenticator->authenticate = htpasswd_auth;
@@ -155,7 +155,7 @@
         free(state);
         free(authenticator);
         ERROR0("No filename given in options for authenticator.");
-        return NULL;
+        return -1;
     }
 
     authenticator->state = state;
@@ -164,7 +164,7 @@
 
     thread_rwlock_create(&state->file_rwlock);
 
-    return authenticator;
+    return 0;
 }
 
 int auth_htpasswd_existing_user(auth_t *auth, const char *username)
@@ -268,7 +268,7 @@
     }
     tmpfile_len = strlen(state->filename) + 6;
     tmpfile = calloc(1, tmpfile_len);
-    sprintf(tmpfile, ".%s.tmp", state->filename);
+    sprintf(tmpfile, "%s.tmp", state->filename);
 
     tmp_passwdfile = fopen(tmpfile, "wb");
 

Modified: icecast/branches/kh/icecast/src/auth_htpasswd.h
===================================================================
--- icecast/branches/kh/icecast/src/auth_htpasswd.h	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/auth_htpasswd.h	2005-04-05 02:09:58 UTC (rev 9111)
@@ -17,7 +17,7 @@
 #include <config.h>
 #endif
 
-auth_t *auth_get_htpasswd_auth(config_options_t *options);
+void auth_get_htpasswd_auth (auth_t *auth, config_options_t *options);
 
 #endif
 

Modified: icecast/branches/kh/icecast/src/auth_url.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_url.c	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/auth_url.c	2005-04-05 02:09:58 UTC (rev 9111)
@@ -17,7 +17,7 @@
  * be handled. The request will have POST information about the request in
  * the form of
  *
- * action=auth&id=1&mount=/live&user=fred&pass=mypass&ip=127.0.0.1&agent=""
+ * action=auth&client=1&mount=/live&user=fred&pass=mypass&ip=127.0.0.1&agent=""
  *
  * For a user to be accecpted the following HTTP header needs
  * to be returned
@@ -27,10 +27,10 @@
  * On client disconnection another request is sent to that same URL with the
  * POST information of
  *
- * action=remove&id=1&mount=/live&user=fred&pass=mypass&duration=3600
+ * action=remove&client=1&mount=/live&user=fred&pass=mypass&duration=3600
  *
- * id refers to the icecast client identification, mount refers to the
- * mountpoint (beginning with /) and duration is the amount of time in
+ * client refers to the icecast client identification number, mount refers
+ * to the mountpoint (beginning with /) and duration is the amount of time in
  * seconds
  */
 
@@ -64,23 +64,15 @@
     char *removeurl;
     char *username;
     char *password;
+    CURL *handle;
+    char errormsg [CURL_ERROR_SIZE];
 } auth_url;
 
-typedef struct {
-    char *mount;
-    client_t *client;
-    CURL *auth_server;
-    char *addurl;
-    char *removeurl;
-    int authenticated;
-    char *username;
-    char *password;
-} auth_client;
 
-
 static void auth_url_clear(auth_t *self)
 {
     auth_url *url = self->state;
+    curl_easy_cleanup (url->handle);
     free(url->username);
     free(url->password);
     free(url->removeurl);
@@ -93,9 +85,10 @@
 {
     auth_client *auth_user = stream;
     unsigned bytes = size * nmemb;
+    client_t *client = auth_user->client;
 
-    if (strncasecmp (ptr, "icecast-auth-user: 1", 20) == 0)
-        auth_user->authenticated = 1;
+    if (strncasecmp (ptr, "icecast-auth-user: 1\r\n", 22) == 0)
+        client->authenticated = 1;
 
     return (int)bytes;
 }
@@ -107,205 +100,97 @@
 }
 
 
-static void *auth_removeurl_thread (void *arg)
+static auth_result auth_removeurl_client (auth_client *auth_user)
 {
-    auth_client *auth_user = arg;
     client_t *client = auth_user->client;
-    CURL *handle;
+    auth_t *auth = client->auth;
+    auth_url *url = auth->state;
+    time_t duration = time(NULL) - client->con->con_time;
+    char *username, *password, *mount;
     char post[1024];
 
-    if (auth_user->removeurl)
-    {
-        time_t duration = time(NULL) - client->con->con_time;
-        char *username, *password;
+    if (url->removeurl == NULL)
+        return AUTH_OK;
+    username = util_url_escape (client->username);
+    password = util_url_escape (client->password);
+    mount = util_url_escape (auth_user->mount);
 
-        DEBUG0("starting auth thread");
-        username = util_url_escape (client->username);
-        password = util_url_escape (client->password);
-        snprintf (post, sizeof (post), "action=remove&id=%ld&mount=%s&user=%s&pass=%s&duration=%lu",
-                client->con->id, auth_user->mount, username, password, (long unsigned)duration);
-        free (username);
-        free (password);
-        handle = curl_easy_init ();
-        if (handle)
-        {
-            int res = 0;
-            char errormsg [CURL_ERROR_SIZE];
-            char *userpass = NULL;
+    snprintf (post, sizeof (post),
+            "action=remove&client=%lu&mount=%s&user=%s&pass=%s&duration=%lu",
+            client->con->id, mount, username, password, (long unsigned)duration);
+    free (mount);
+    free (username);
+    free (password);
 
-            if (auth_user->username && auth_user->password)
-            {
-                unsigned len = strlen (auth_user->username) + strlen (auth_user->password) + 2;
-                userpass = malloc (len);
-                snprintf (userpass, len, "%s:%s", auth_user->username, auth_user->password);
-                curl_easy_setopt (handle, CURLOPT_USERPWD, userpass);
-            }
-            curl_easy_setopt (handle, CURLOPT_URL, auth_user->removeurl);
-            curl_easy_setopt (handle, CURLOPT_POSTFIELDS, post);
-            curl_easy_setopt (handle, CURLOPT_HEADERFUNCTION, handle_returned_header);
-            curl_easy_setopt (handle, CURLOPT_WRITEFUNCTION, handle_returned_data);
-            curl_easy_setopt (handle, CURLOPT_WRITEHEADER, auth_user);
-            curl_easy_setopt (handle, CURLOPT_WRITEDATA, handle);
-            curl_easy_setopt (handle, CURLOPT_NOSIGNAL, 1L);
-            curl_easy_setopt (handle, CURLOPT_TIMEOUT, 15L);
-            curl_easy_setopt (handle, CURLOPT_ERRORBUFFER, errormsg);
-            res = curl_easy_perform (handle);
-            curl_easy_cleanup (handle);
-            free (userpass);
+    curl_easy_setopt (url->handle, CURLOPT_URL, url->removeurl);
+    curl_easy_setopt (url->handle, CURLOPT_POSTFIELDS, post);
+    curl_easy_setopt (url->handle, CURLOPT_WRITEHEADER, auth_user);
 
-            if (res)
-                WARN2 ("auth to server %s failed with %s", auth_user->removeurl, errormsg);
-        }
-    }
-    auth_close_client (client);
+    if (curl_easy_perform (url->handle))
+        WARN2 ("auth to server %s failed with %s", url->removeurl, url->errormsg);
 
-    free (auth_user->username);
-    free (auth_user->password);
-    free (auth_user->mount);
-    free (auth_user->removeurl);
-    free (auth_user);
-    return NULL;
+    /* these are needed so the client is not added back onto the auth list */
+    auth_release (client->auth);
+    client->auth = NULL;
+
+    return AUTH_OK;
 }
 
 
-static void *auth_url_thread (void *arg)
+static auth_result auth_addurl_client (auth_client *auth_user)
 {
-    auth_client *auth_user = arg;
     client_t *client = auth_user->client;
+    auth_t *auth = client->auth;
+    auth_url *url = auth->state;
     int res = 0;
     char *agent, *user_agent, *username, *password;
-    CURL *handle;
+    char *mount, *ipaddr;
     char post[1024];
 
-    DEBUG0("starting auth thread");
     agent = httpp_getvar (client->parser, "user-agent");
     if (agent == NULL)
         agent = "-";
     user_agent = util_url_escape (agent);
     username  = util_url_escape (client->username);
     password  = util_url_escape (client->password);
-    snprintf (post, 1024,"action=auth&id=%ld&mount=%s&user=%s&pass=%s&ip=%s&agent=%s",
-            client->con->id, auth_user->mount, username, password,
-            client->con->ip, user_agent);
+    mount = util_url_escape (auth_user->mount);
+    ipaddr = util_url_escape (client->con->ip);
+
+    snprintf (post, sizeof (post),
+            "action=auth&client=%lu&mount=%s&user=%s&pass=%s&ip=%s&agent=%s",
+            client->con->id, mount, username, password, ipaddr, user_agent);
+    free (mount);
     free (user_agent);
     free (username);
     free (password);
+    free (ipaddr);
 
-    handle = curl_easy_init ();
-    if (handle)
-    {
-        char errormsg [CURL_ERROR_SIZE];
-        char *userpass = NULL;
+    curl_easy_setopt (url->handle, CURLOPT_URL, url->addurl);
+    curl_easy_setopt (url->handle, CURLOPT_POSTFIELDS, post);
+    curl_easy_setopt (url->handle, CURLOPT_WRITEHEADER, auth_user);
 
-        if (auth_user->username && auth_user->password)
-        {
-            unsigned len = strlen (auth_user->username) + strlen (auth_user->password) + 2;
-            userpass = malloc (len);
-            snprintf (userpass, len, "%s:%s", auth_user->username, auth_user->password);
-            curl_easy_setopt (handle, CURLOPT_USERPWD, userpass);
-        }
+    res = curl_easy_perform (url->handle);
 
-        curl_easy_setopt (handle, CURLOPT_URL, auth_user->addurl);
-        curl_easy_setopt (handle, CURLOPT_POSTFIELDS, post);
-        curl_easy_setopt (handle, CURLOPT_HEADERFUNCTION, handle_returned_header);
-        curl_easy_setopt (handle, CURLOPT_WRITEFUNCTION, handle_returned_data);
-        curl_easy_setopt (handle, CURLOPT_WRITEHEADER, auth_user);
-        curl_easy_setopt (handle, CURLOPT_WRITEDATA, handle);
-        curl_easy_setopt (handle, CURLOPT_NOSIGNAL, 1L);
-        curl_easy_setopt (handle, CURLOPT_TIMEOUT, 15L);
-        curl_easy_setopt (handle, CURLOPT_ERRORBUFFER, errormsg);
-        res = curl_easy_perform (handle);
-        curl_easy_cleanup (handle);
-        free (userpass);
-        // auth_user->authenticated = 1;
-
-        if (res)
+    if (res)
+    {
+        WARN2 ("auth to server %s failed with %s", url->addurl, url->errormsg);
+        return AUTH_FAILED;
+    }
+    /* we received a response, lets see what it is */
+    if (client->authenticated)
+    {
+        if (auth_postprocess_client (auth_user) < 0)
         {
-            WARN2 ("auth to server %s failed with %s", auth_user->addurl, errormsg);
-            auth_failed_client (auth_user->mount);
-            auth_close_client (client);
+            /* do cleanup, and exit as the remove does cleanup as well */
+            return AUTH_FAILED;
         }
-        else
-        {
-            /* we received a response, lets see what it is */
-            if (auth_user->authenticated)
-            {
-                if (auth_postprocess_client (auth_user->mount, client) < 0)
-                {
-                    /* do cleanup, and exit as the remove does cleanup as well */
-                    free (auth_user->addurl);
-                    auth_user->addurl = NULL;
-                    auth_failed_client (auth_user->mount);
-                    auth_removeurl_thread (auth_user);
-                    return NULL;
-                }
-            }
-            else
-            {
-                DEBUG0 ("client authentication failed");
-                auth_failed_client (auth_user->mount);
-                auth_close_client (client);
-            }
-        }
+        return AUTH_OK;
     }
-    else
-    {
-        auth_failed_client (auth_user->mount);
-        auth_close_client (client);
-    }
-
-    free (auth_user->username);
-    free (auth_user->password);
-    free (auth_user->mount);
-    free (auth_user->addurl);
-    free (auth_user->removeurl);
-    free (auth_user);
-
-    return NULL;
+    return AUTH_FAILED;
 }
 
 
-static void auth_remove_url_client (source_t *source, client_t *client)
-{
-    auth_client *auth_user = calloc (1, sizeof (auth_client));
-    auth_url *urlinfo = source->authenticator->state;
 
-    if (auth_user == NULL)
-        return;
-
-    if (urlinfo->username)
-        auth_user->username = strdup (urlinfo->username);
-    if (urlinfo->password)
-        auth_user->password = strdup (urlinfo->password);
-    if (urlinfo->removeurl)
-        auth_user->removeurl = strdup (urlinfo->removeurl);
-    auth_user->mount = strdup (source->mount);
-    auth_user->client = client;
-    thread_create("AuthRemove by URL thread", auth_removeurl_thread,
-            auth_user, THREAD_DETACHED);
-}
-
-
-static auth_result auth_url_client (source_t *source, client_t *client)
-{
-    auth_client *auth_user = calloc (1, sizeof (auth_client));
-    auth_url *urlinfo = source->authenticator->state;
-
-    if (auth_user == NULL)
-        return AUTH_FAILED;
-
-    if (urlinfo->username)
-        auth_user->username = strdup (urlinfo->username);
-    if (urlinfo->password)
-        auth_user->password = strdup (urlinfo->password);
-    auth_user->addurl = strdup (urlinfo->addurl);
-    auth_user->removeurl = strdup (urlinfo->removeurl);
-    auth_user->mount = strdup (source->mount);
-    auth_user->client = client;
-    thread_create("Auth by URL thread", auth_url_thread, auth_user, THREAD_DETACHED);
-    return AUTH_OK;
-}
-
 static auth_result auth_url_adduser(auth_t *auth, const char *username, const char *password)
 {
     return AUTH_FAILED;
@@ -321,33 +206,46 @@
     return AUTH_FAILED;
 }
 
-auth_t *auth_get_url_auth (config_options_t *options)
+int auth_get_url_auth (auth_t *authenticator, config_options_t *options)
 {
-    auth_t *authenticator = calloc(1, sizeof(auth_t));
-    auth_url *state;
+    auth_url *url_info;
 
-    authenticator->authenticate = auth_url_client;
+    authenticator->authenticate = auth_addurl_client;
     authenticator->free = auth_url_clear;
     authenticator->adduser = auth_url_adduser;
     authenticator->deleteuser = auth_url_deleteuser;
     authenticator->listuser = auth_url_listuser;
-    authenticator->release_client = auth_remove_url_client;
+    authenticator->release_client = auth_removeurl_client;
 
-    state = calloc(1, sizeof(auth_url));
+    url_info = calloc(1, sizeof(auth_url));
 
     while(options) {
         if(!strcmp(options->name, "username"))
-            state->username = strdup(options->value);
+            url_info->username = strdup (options->value);
         if(!strcmp(options->name, "password"))
-            state->password = strdup(options->value);
+            url_info->password = strdup (options->value);
         if(!strcmp(options->name, "add"))
-            state->addurl = strdup(options->value);
+            url_info->addurl = strdup (options->value);
         if(!strcmp(options->name, "remove"))
-            state->removeurl = strdup(options->value);
+            url_info->removeurl = strdup (options->value);
         options = options->next;
     }
-    authenticator->state = state;
+    url_info->handle = curl_easy_init ();
+    if (url_info->handle == NULL)
+    {
+        free (url_info);
+        free (authenticator);
+        return -1;
+    }
+    curl_easy_setopt (url_info->handle, CURLOPT_HEADERFUNCTION, handle_returned_header);
+    curl_easy_setopt (url_info->handle, CURLOPT_WRITEFUNCTION, handle_returned_data);
+    curl_easy_setopt (url_info->handle, CURLOPT_WRITEDATA, url_info->handle);
+    curl_easy_setopt (url_info->handle, CURLOPT_NOSIGNAL, 1L);
+    curl_easy_setopt (url_info->handle, CURLOPT_TIMEOUT, 15L);
+    curl_easy_setopt (url_info->handle, CURLOPT_ERRORBUFFER, &url_info->errormsg[0]);
+
+    authenticator->state = url_info;
     INFO0("URL based authentication setup");
-    return authenticator;
+    return 0;
 }
 

Modified: icecast/branches/kh/icecast/src/auth_url.h
===================================================================
--- icecast/branches/kh/icecast/src/auth_url.h	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/auth_url.h	2005-04-05 02:09:58 UTC (rev 9111)
@@ -17,7 +17,7 @@
 #include <config.h>
 #endif
 
-auth_t *auth_get_url_auth (config_options_t *options);
+int *auth_get_url_auth (auth_t *authenticator, config_options_t *options);
 
 #endif
 

Modified: icecast/branches/kh/icecast/src/cfgfile.c
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.c	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/cfgfile.c	2005-04-05 02:09:58 UTC (rev 9111)
@@ -206,6 +206,7 @@
             free(option);
             option = nextopt;
         }
+        auth_release (mount->auth);
 
         free(mount);
         mount = nextmount;
@@ -530,8 +531,6 @@
     mount_proxy *mount = calloc(1, sizeof(mount_proxy));
     mount_proxy *current = configuration->mounts;
     mount_proxy *last=NULL;
-    xmlNodePtr option;
-    config_options_t *last_option;
     
     while(current) {
         last = current;
@@ -613,35 +612,7 @@
             if(tmp) xmlFree(tmp);
         }
         else if (strcmp(node->name, "authentication") == 0) {
-            mount->auth_type = xmlGetProp(node, "type");
-            option = node->xmlChildrenNode;
-            last_option = NULL;
-            while(option != NULL) {
-                if(strcmp(option->name, "option") == 0) {
-                    config_options_t *opt = malloc(sizeof(config_options_t));
-                    opt->name = xmlGetProp(option, "name");
-                    if(!opt->name) {
-                        free(opt);
-                        option = option->next;
-                        continue;
-                    }
-                    opt->value = xmlGetProp(option, "value");
-                    if(!opt->value) {
-                        free(opt->name);
-                        free(opt);
-                        option = option->next;
-                        continue;
-                    }
-                    opt->next = NULL;
-
-                    if(last_option)
-                        last_option->next = opt;
-                    else
-                        mount->auth_options = opt;
-                    last_option = opt;
-                }
-                option = option->next;
-            }
+            mount->auth = auth_get_authenticator (node);
         }
         else if (strcmp(node->name, "on-connect") == 0) {
             mount->on_connect = (char *)xmlNodeListGetString(
@@ -1029,3 +1000,16 @@
 }
 
 
+mount_proxy *config_find_mount (ice_config_t *config, const char *mount)
+{
+    mount_proxy *mountinfo = config->mounts;
+
+    while (mountinfo)
+    {
+        if (strcmp (mountinfo->mountname, mount) == 0)
+            break;
+        mountinfo = mountinfo->next;
+    }
+    return mountinfo;
+}
+

Modified: icecast/branches/kh/icecast/src/cfgfile.h
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.h	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/cfgfile.h	2005-04-05 02:09:58 UTC (rev 9111)
@@ -23,6 +23,7 @@
 
 #include "thread/thread.h"
 #include "avl/avl.h"
+#include "auth.h"
 #include "global.h"
 
 typedef struct ice_config_dir_tag
@@ -66,6 +67,7 @@
     int mp3_meta_interval; /* outgoing per-stream metadata interval */
 
     char *auth_type; /* Authentication type */
+    struct auth_tag *auth;
     char *cluster_password;
     config_options_t *auth_options; /* Options for this type */
     char *on_connect;
@@ -171,6 +173,7 @@
 int config_parse_cmdline(int arg, char **argv);
 void config_set_config(ice_config_t *config);
 void config_clear(ice_config_t *config);
+mount_proxy *config_find_mount (ice_config_t *config, const char *mount);
 
 int config_rehash(void);
 

Modified: icecast/branches/kh/icecast/src/client.c
===================================================================
--- icecast/branches/kh/icecast/src/client.c	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/client.c	2005-04-05 02:09:58 UTC (rev 9111)
@@ -58,6 +58,10 @@
 {
     if (client == NULL)
         return;
+
+    if (release_client (client))
+        return;
+
     /* write log entry if ip is set (some things don't set it, like outgoing 
      * slave requests
      */
@@ -81,6 +85,7 @@
     /* drop ref counts if need be */
     if (client->refbuf)
         refbuf_release (client->refbuf);
+
     /* we need to free client specific format data (if any) */
     if (client->free_client_data)
         client->free_client_data (client);

Modified: icecast/branches/kh/icecast/src/client.h
===================================================================
--- icecast/branches/kh/icecast/src/client.h	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/client.h	2005-04-05 02:09:58 UTC (rev 9111)
@@ -17,9 +17,9 @@
 */
 #ifndef __CLIENT_H__
 #define __CLIENT_H__
-
+
 #ifdef HAVE_AIO
-#include <aio.h>
+#include <aio.h>
 #endif
 
 #include "connection.h"
@@ -53,6 +53,9 @@
     /* client is a slave server */
     int is_slave;
 
+    /* auth used for this client */
+    struct auth_tag *auth;
+
     /* Client username, if authenticated */
     char *username;
 

Modified: icecast/branches/kh/icecast/src/connection.c
===================================================================
--- icecast/branches/kh/icecast/src/connection.c	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/connection.c	2005-04-05 02:09:58 UTC (rev 9111)
@@ -19,8 +19,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
 #ifdef HAVE_POLL
 #include <sys/poll.h>
 #endif
@@ -747,10 +745,7 @@
 static void _handle_get_request(connection_t *con,
         http_parser_t *parser, char *passed_uri)
 {
-    char *fullpath;
     client_t *client;
-    int bytes;
-    struct stat statbuf;
     int fileserve;
     char *host = NULL;
     int port;
@@ -811,66 +806,6 @@
         free (host);
         return;
     }
-
-    /* Here we are parsing the URI request to see
-    ** if the extension is .xsl, if so, then process
-    ** this request as an XSLT request
-    */
-    fullpath = util_get_path_from_normalised_uri(uri);
-    if (util_check_valid_extension(fullpath) == XSLT_CONTENT) {
-        /* If the file exists, then transform it, otherwise, write a 404 */
-        if (stat(fullpath, &statbuf) == 0) {
-            DEBUG0("Stats request, sending XSL transformed stats");
-            client->respcode = 200;
-            bytes = sock_write(client->con->sock, 
-                    "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
-            if(bytes > 0) client->con->sent_bytes = bytes;
-            stats_transform_xslt(client, fullpath);
-            client_destroy(client);
-        }
-        else {
-            client_send_404(client, "The file you requested could not be found");
-        }
-        free(fullpath);
-        if (uri != passed_uri) free (uri);
-        free (host);
-        return;
-    }
-    else if(fileserve && stat(fullpath, &statbuf) == 0 && 
-#ifdef _WIN32
-            ((statbuf.st_mode) & _S_IFREG))
-#else
-            S_ISREG(statbuf.st_mode)) 
-#endif
-    {
-        fserve_client_create(client, fullpath);
-        free(fullpath);
-        if (uri != passed_uri) free (uri);
-        free (host);
-        return;
-    }
-    free(fullpath);
-
-    if(strcmp(util_get_extension(uri), "m3u") == 0) {
-        char *sourceuri = strdup(uri);
-        char *dot = strrchr(sourceuri, '.');
-        *dot = 0;
-        client->respcode = 200;
-        bytes = sock_write(client->con->sock,
-                "HTTP/1.0 200 OK\r\n"
-                "Content-Type: audio/x-mpegurl\r\n\r\n"
-                "http://%s:%d%s\r\n", 
-                host, 
-                port,
-                sourceuri
-                );
-        if(bytes > 0) client->con->sent_bytes = bytes;
-        client_destroy(client);
-        free(sourceuri);
-        if (uri != passed_uri) free (uri);
-        free (host);
-        return;
-    }
     free (host);
 
     global_lock();

Modified: icecast/branches/kh/icecast/src/fserve.c
===================================================================
--- icecast/branches/kh/icecast/src/fserve.c	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/fserve.c	2005-04-05 02:09:58 UTC (rev 9111)
@@ -21,6 +21,7 @@
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #endif
+#include <errno.h>
 
 #ifdef HAVE_POLL
 #include <sys/poll.h>
@@ -311,10 +312,10 @@
     return NULL;
 }
 
-const char *fserve_content_type (char *path)
+const char *fserve_content_type (const char *path)
 {
-    char *ext = util_get_extension(path);
-    mime_type exttype = {ext, NULL};
+    const char *ext = util_get_extension(path);
+    mime_type exttype = {strdup(ext), NULL};
     void *result;
 
     if (!avl_get_by_key (mimetypes, &exttype, &result))
@@ -353,7 +354,7 @@
 }
 
 
-int fserve_client_create(client_t *httpclient, char *path)
+int fserve_client_create(client_t *httpclient, const char *path)
 {
     fserve_t *client = calloc(1, sizeof(fserve_t));
     int bytes;
@@ -364,25 +365,101 @@
     int64_t new_content_len = 0;
     int64_t rangenumber = 0;
     int ret = 0;
+    char *fullpath;
+    int m3u_requested = 0, m3u_file_available = 1;
 
+    // server limit check should be done earlier
     client_limit = config->client_limit;
     config_release_config();
 
-    DEBUG1 ("handle file %s", path);
-    client->file = fopen(path, "rb");
-    if(!client->file) {
-        client_send_404(httpclient, "File not readable");
+    fullpath = util_get_path_from_normalised_uri (path);
+    INFO2 ("handle file %s (%s)", path, fullpath);
+
+    if (strcmp (util_get_extension (fullpath), "m3u") == 0)
+        m3u_requested = 1;
+
+    /* check for the actual file */
+    if (stat (fullpath, &file_buf) != 0)
+    {
+        /* the m3u can be generated, but send an m3u file if available */
+        if (m3u_requested == 0)
+        {
+            WARN2 ("req for file \"%s\" %s", fullpath, strerror (errno));
+            client_send_404 (httpclient, "The file you requested could not be found");
+            free (fullpath);
+            return -1;
+        }
+        m3u_file_available = 0;
+    }
+
+    if (m3u_requested && m3u_file_available == 0)
+    {
+        char *host = httpp_getvar (httpclient->parser, "host");
+        char *sourceuri = strdup (path);
+        char *dot = strrchr(sourceuri, '.');
+        int port = 8002;
+        *dot = 0;
+        DEBUG1 ("host passed is %s", host);
+        httpclient->respcode = 200;
+        if (host == NULL)
+        {
+            config = config_get_config();
+            host = strdup (config->hostname);
+            port = config->port;
+            config_release_config();
+            bytes = sock_write (httpclient->con->sock,
+                    "HTTP/1.0 200 OK\r\n"
+                    "Content-Type: audio/x-mpegurl\r\n\r\n"
+                    "http://%s:%d%s\r\n", 
+                    host, port,
+                    sourceuri
+                    );
+            free (host);
+        }
+        else
+        {
+            bytes = sock_write (httpclient->con->sock,
+                    "HTTP/1.0 200 OK\r\n"
+                    "Content-Type: audio/x-mpegurl\r\n\r\n"
+                    "http://%s%s\r\n", 
+                    host, 
+                    sourceuri
+                    );
+        }
+        if (bytes > 0) httpclient->con->sent_bytes = bytes;
+        client_destroy (httpclient);
+        free (sourceuri);
+        free (fullpath);
         return -1;
     }
 
+    if (util_check_valid_extension (fullpath) == XSLT_CONTENT)
+    {
+        /* If the file exists, then transform it, otherwise, write a 404 */
+        DEBUG0("Stats request, sending XSL transformed stats");
+        httpclient->respcode = 200;
+        bytes = sock_write(httpclient->con->sock, 
+                "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
+        if(bytes > 0) httpclient->con->sent_bytes = bytes;
+        stats_transform_xslt (httpclient, fullpath);
+        client_destroy (httpclient);
+        free (fullpath);
+        return -1;
+    }
+
+    client->file = fopen (fullpath, "rb");
+    if (client->file == NULL)
+    {
+        client_send_404 (httpclient, "File not readable");
+        return -1;
+    }
+
     client->client = httpclient;
     client->ready = 0;
     client_set_queue (httpclient, NULL);
     httpclient->refbuf = refbuf_new (BUFSIZE);
     httpclient->pos = BUFSIZE;
-    if (stat(path, &file_buf) == 0) {
-        client->content_length = (int64_t)file_buf.st_size;
-    }
+    client->content_length = (int64_t)file_buf.st_size;
 
     global_lock();
     if(global.clients >= client_limit) {

Modified: icecast/branches/kh/icecast/src/fserve.h
===================================================================
--- icecast/branches/kh/icecast/src/fserve.h	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/fserve.h	2005-04-05 02:09:58 UTC (rev 9111)
@@ -28,8 +28,8 @@
 
 void fserve_initialize(void);
 void fserve_shutdown(void);
-int fserve_client_create(client_t *httpclient, char *path);
-const char *fserve_content_type (char *path);
+int fserve_client_create(client_t *httpclient, const char *path);
+const char *fserve_content_type (const char *path);
 
 
 #endif

Modified: icecast/branches/kh/icecast/src/main.c
===================================================================
--- icecast/branches/kh/icecast/src/main.c	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/main.c	2005-04-05 02:09:58 UTC (rev 9111)
@@ -506,6 +506,7 @@
 
     /* Do this after logging init */
     slave_initialize();
+    auth_initialise ();
 
     _server_proc();
 

Modified: icecast/branches/kh/icecast/src/source.c
===================================================================
--- icecast/branches/kh/icecast/src/source.c	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/source.c	2005-04-05 02:09:58 UTC (rev 9111)
@@ -250,9 +250,6 @@
     }
     source->format = NULL;
 
-    auth_clear (source->authenticator);
-    source->authenticator = NULL;
-
     source->burst_point = NULL;
     source->burst_size = 0;
     source->burst_offset = 0;
@@ -961,11 +958,7 @@
     stats_event_dec(NULL, "clients");
 
     client_set_queue (client, NULL);
-    if (source && source->authenticator && source->authenticator->release_client)
-    {
-        source->authenticator->release_client (source, client);
-        return 0;
-    }
+
     /* if no response has been sent then send a 404 */
     if (client->respcode == 0)
         client_send_404 (client, "Mount unavailable");
@@ -1024,13 +1017,6 @@
         free (source->fallback_mount);
         source->fallback_mount = strdup (mountinfo->fallback_mount);
     }
-
-    if (mountinfo->auth_type != NULL)
-    {
-        source->authenticator = auth_get_authenticator(
-                mountinfo->auth_type, mountinfo->auth_options);
-        stats_event(source->mount, "authenticator", mountinfo->auth_type);
-    }
     if (mountinfo->dumpfile)
     {
         free (source->dumpfilename);
@@ -1097,8 +1083,6 @@
     source->burst_size = config->burst_size;
 
     source->dumpfilename = NULL;
-    auth_clear (source->authenticator);
-    source->authenticator = NULL;
 
     while (mountproxy)
     {

Modified: icecast/branches/kh/icecast/src/source.h
===================================================================
--- icecast/branches/kh/icecast/src/source.h	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/source.h	2005-04-05 02:09:58 UTC (rev 9111)
@@ -20,8 +20,6 @@
 
 #include <stdio.h>
 
-struct auth_tag;
-
 typedef struct source_tag
 {
     client_t *client;
@@ -56,7 +54,6 @@
     long max_listeners;
     int yp_public;
     int yp_prevent;
-    struct auth_tag *authenticator;
     int fallback_override;
     int fallback_when_full;
     int no_mount;

Modified: icecast/branches/kh/icecast/src/util.c
===================================================================
--- icecast/branches/kh/icecast/src/util.c	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/util.c	2005-04-05 02:09:58 UTC (rev 9111)
@@ -131,7 +131,7 @@
     return ret;
 }
 
-char *util_get_extension(char *path) {
+const char *util_get_extension(const char *path) {
     char *ext = strrchr(path, '.');
 
     if(ext == NULL)
@@ -225,7 +225,7 @@
     }
 }
 
-char *util_get_path_from_normalised_uri(char *uri) {
+char *util_get_path_from_normalised_uri(const char *uri) {
     char *fullpath;
     char *webroot;
     ice_config_t *config = config_get_config();

Modified: icecast/branches/kh/icecast/src/util.h
===================================================================
--- icecast/branches/kh/icecast/src/util.h	2005-04-03 14:19:14 UTC (rev 9110)
+++ icecast/branches/kh/icecast/src/util.h	2005-04-05 02:09:58 UTC (rev 9111)
@@ -22,9 +22,9 @@
 int util_timed_wait_for_fd(int fd, int timeout);
 int util_read_header(int sock, char *buff, unsigned long len, int entire);
 int util_check_valid_extension(char *uri);
-char *util_get_extension(char *path);
+const char *util_get_extension(const char *path);
 char *util_get_path_from_uri(char *uri);
-char *util_get_path_from_normalised_uri(char *uri);
+char *util_get_path_from_normalised_uri(const char *uri);
 char *util_normalise_uri(char *uri);
 char *util_base64_encode(char *data);
 char *util_base64_decode(unsigned char *input);



More information about the commits mailing list