[xiph-cvs] cvs commit: icecast/src connection.c connection.h source.c source.h

Karl Heyes karl at xiph.org
Thu Feb 19 08:32:27 PST 2004



karl        04/02/19 11:32:27

  Modified:    src      connection.c connection.h source.c source.h
  Log:
  functions to allow for reserving a source_t with a mountpoint

Revision  Changes    Path
1.86      +92 -2     icecast/src/connection.c

Index: connection.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/connection.c,v
retrieving revision 1.85
retrieving revision 1.86
diff -u -r1.85 -r1.86
--- connection.c	19 Feb 2004 15:24:06 -0000	1.85
+++ connection.c	19 Feb 2004 16:32:23 -0000	1.86
@@ -426,9 +426,99 @@
     _signal_pool();
 }
 
-/* TODO: Make this return an appropriate error code so that we can use HTTP
- * codes where appropriate
+
+/* Called when activating a source. Verifies that the source count is not
+ * exceeded and applies any initial parameters.
  */
+int connection_complete_source (source_t *source)
+{
+    ice_config_t *config = config_get_config();
+
+    global_lock ();
+    DEBUG1 ("sources count is %d", global.sources);
+
+    if (global.sources < config->source_limit)
+    {
+        char *contenttype;
+        mount_proxy *mountproxy = config->mounts;
+        format_type_t format_type;
+
+        /* setup format handler */
+        contenttype = httpp_getvar (source->parser, "content-type");
+        if (contenttype != NULL)
+        {
+            format_type = format_get_type (contenttype);
+
+            if (format_type == FORMAT_ERROR)
+            {
+                global_unlock();
+                config_release_config();
+                if (source->client)
+                    client_send_404 (source->client, "Content-type not supported");
+                WARN1("Content-type \"%s\" not supported, dropping source", contenttype);
+                return -1;
+            }
+        }
+        else
+        {
+            WARN0("No content-type header, falling back to backwards compatibility mode"
+                    "for icecast 1.x relays. Assuming content is mp3.");
+            format_type = FORMAT_TYPE_MP3;
+        }
+        source->format = format_get_plugin (format_type, source->mount, source->parser);
+
+        if (source->format == NULL)
+        {
+            global_unlock();
+            config_release_config();
+            if (source->client)
+                client_send_404 (source->client, "internal format allocation problem");
+            WARN1 ("plugin format failed for \"%s\"", source->mount);
+            return -1;
+        }
+
+        global.sources++;
+        global_unlock();
+
+        /* for relays, we don't yet have a client, however we do require one
+         * to retrieve the stream from.  This is created here, quite late,
+         * because we can't use this client to return an error code/message,
+         * so we only do this once we know we're going to accept the source.
+         */
+        if (source->client == NULL)
+            source->client = client_create (source->con, source->parser);
+
+        sock_set_blocking (source->con->sock, SOCK_NONBLOCK);
+
+        while (mountproxy)
+        {
+            if (strcmp (mountproxy->mountname, source->mount) == 0)
+            {
+                source_apply_mount (source, mountproxy);
+                break;
+            }
+            mountproxy = mountproxy->next;
+        }
+        config_release_config();
+
+        source->shutdown_rwlock = &_source_shutdown_rwlock;
+        DEBUG0 ("source is ready to start");
+
+        return 0;
+    }
+    WARN1("Request to add source when maximum source limit"
+            "reached %d", global.sources);
+
+    global_unlock();
+    config_release_config();
+
+    if (source->client)
+        client_send_404 (source->client, "too many sources connected");
+
+    return -1;
+}
+
+
 int connection_create_source(client_t *client, connection_t *con, http_parser_t *parser, char *mount) {
     source_t *source;
     char *contenttype;

<p><p>1.14      +2 -0      icecast/src/connection.h

Index: connection.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/connection.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- connection.h	29 Jan 2004 01:02:06 -0000	1.13
+++ connection.h	19 Feb 2004 16:32:23 -0000	1.14
@@ -21,6 +21,7 @@
 #include "net/sock.h"
 
 struct _client_tag;
+struct source_tag;
 
 typedef struct connection_tag
 {
@@ -49,6 +50,7 @@
 connection_t *create_connection(sock_t sock, sock_t serversock, char *ip);
 int connection_create_source(struct _client_tag *client, connection_t *con, 
         http_parser_t *parser, char *mount);
+int connection_complete_source (struct source_tag *source);
 
 void connection_inject_event(int eventnum, void *event_data);
 

<p><p>1.72      +131 -0    icecast/src/source.c

Index: source.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/source.c,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -r1.71 -r1.72
--- source.c	19 Feb 2004 14:48:31 -0000	1.71
+++ source.c	19 Feb 2004 16:32:23 -0000	1.72
@@ -63,6 +63,44 @@
 static int _free_client(void *key);
 static int _parse_audio_info(source_t *source, char *s);
 
+/* Allocate a new source with the stated mountpoint, if one already
+ * exists with that mountpoint in the global source tree then return
+ * NULL.
+ */
+source_t *source_reserve (const char *mount)
+{
+    source_t *src = NULL;
+
+    do
+    {
+        avl_tree_wlock (global.source_tree);
+        src = source_find_mount_raw (mount);
+        if (src)
+        {
+            src = NULL;
+            break;
+        }
+
+        src = calloc (1, sizeof(source_t));
+        if (src == NULL)
+            break;
+
+        src->client_tree = avl_tree_new(_compare_clients, NULL);
+        src->pending_tree = avl_tree_new(_compare_clients, NULL);
+
+        /* make duplicates for strings or similar */
+        src->mount = strdup (mount);
+        src->max_listeners = -1;
+
+        avl_insert (global.source_tree, src);
+
+    } while (0);
+
+    avl_tree_unlock (global.source_tree);
+    return src;
+}
+
+
 source_t *source_create(client_t *client, connection_t *con, 
     http_parser_t *parser, const char *mount, format_type_t type, 
     mount_proxy *mountinfo)
@@ -204,6 +242,62 @@
     return strcmp(srca->mount, srcb->mount);
 }
 
+
+void source_clear_source (source_t *source)
+{
+#ifdef USE_YP
+     int i;
+#endif
+    DEBUG1 ("clearing source \"%s\"", source->mount);
+    client_destroy(source->client);
+    source->client = NULL;
+
+    /* lets kick off any clients that are left on here */
+    avl_tree_rlock (source->client_tree);
+    while (avl_get_first (source->client_tree))
+    {
+        avl_delete (source->client_tree,
+                avl_get_first (source->client_tree)->key, _free_client);
+    }
+    avl_tree_unlock (source->client_tree);
+
+    avl_tree_rlock (source->pending_tree);
+    while (avl_get_first (source->pending_tree))
+    {
+        avl_delete (source->pending_tree,
+                avl_get_first(source->pending_tree)->key, _free_client);
+    }
+    avl_tree_unlock (source->pending_tree);
+
+    if (source->format && source->format->free_plugin)
+    {
+        source->format->free_plugin (source->format);
+    }
+    source->format = NULL;
+#ifdef USE_YP
+    for (i=0; i<source->num_yp_directories; i++)
+    {
+        yp_destroy_ypdata(source->ypdata[i]);
+        source->ypdata[i] = NULL;
+    }
+    source->num_yp_directories = 0;
+#endif
+    source->listeners = 0;
+    source->no_mount = 0;
+    source->max_listeners = -1;
+    source->yp_public = 0;
+
+    util_dict_free(source->audio_info);
+    source->audio_info = NULL;
+
+    free(source->fallback_mount);
+    source->fallback_mount = NULL;
+
+    free(source->dumpfilename);
+    source->dumpfilename = NULL;
+}
+
+
 int source_free_source(void *key)
 {
     source_t *source = key;
@@ -495,6 +589,7 @@
     }
 
     DEBUG0("Source creation complete");
+    source->running = 1;
 
     /*
     ** Now, if we have a fallback source and override is on, we want
@@ -857,3 +952,39 @@
     }
     return 1;
 }
+
+
+void source_apply_mount (source_t *source, mount_proxy *mountinfo)
+{
+    DEBUG1("Applying mount information for \"%s\"", source->mount);
+    source->max_listeners = mountinfo->max_listeners;
+    source->fallback_override = mountinfo->fallback_override;
+    source->no_mount = mountinfo->no_mount;
+    if (mountinfo->fallback_mount)
+    {
+        source->fallback_mount = strdup (mountinfo->fallback_mount);
+        DEBUG1 ("fallback %s", mountinfo->fallback_mount);
+    }
+    if (mountinfo->auth_type != NULL)
+    {
+        source->authenticator = auth_get_authenticator(
+                mountinfo->auth_type, mountinfo->auth_options);
+    }
+    if (mountinfo->dumpfile)
+    {
+        DEBUG1("Dumping stream to %s", mountinfo->dumpfile);
+        source->dumpfilename = strdup (mountinfo->dumpfile);
+    }
+}
+
+
+void *source_client_thread (void *arg)
+{
+    source_t *source = arg;
+
+    source->send_return = 1;
+    source_main (source);
+    source_free_source (source);
+    return NULL;
+}
+

<p><p>1.19      +4 -0      icecast/src/source.h

Index: source.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/source.h,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- source.h	29 Jan 2004 16:46:54 -0000	1.18
+++ source.h	19 Feb 2004 16:32:26 -0000	1.19
@@ -62,6 +62,10 @@
 source_t *source_create(client_t *client, connection_t *con, 
         http_parser_t *parser, const char *mount, format_type_t type,
         mount_proxy *mountinfo);
+source_t *source_reserve (const char *mount);
+void *source_client_thread (void *arg);
+void source_apply_mount (source_t *source, mount_proxy *mountinfo);
+void source_clear_source (source_t *source);
 source_t *source_find_mount(const char *mount);
 source_t *source_find_mount_raw(const char *mount);
 client_t *source_find_client(source_t *source, int id);

<p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list