[xiph-cvs] cvs commit: icecast/src fserve.c fserve.h Makefile.am config.c config.h connection.c main.c

Michael Smith msmith at xiph.org
Sat Aug 17 22:06:59 PDT 2002



msmith      02/08/18 01:06:58

  Modified:    conf     icecast.xml
               src      Makefile.am config.c config.h connection.c main.c
  Added:       src      fserve.c fserve.h
  Log:
  File serving, from the webroot.

Revision  Changes    Path
1.12      +7 -5      icecast/conf/icecast.xml

Index: icecast.xml
===================================================================
RCS file: /usr/local/cvsroot/icecast/conf/icecast.xml,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- icecast.xml	16 Aug 2002 15:04:04 -0000	1.11
+++ icecast.xml	18 Aug 2002 05:06:58 -0000	1.12
@@ -31,11 +31,13 @@
     <!--<master-update-interval>120</master-update-interval>-->
     <!--<master-password>hackme</master-password>-->
 
-        <paths>
-                <basedir>/usr/local/icecast</basedir>
-                <logdir>/tmp</logdir>
-                <webroot>/usr/local/icecast/web</webroot>
-        </paths>
+    <fileserve>1</fileserve>
+
+    <paths>
+            <basedir>/usr/local/icecast</basedir>
+            <logdir>/tmp</logdir>
+            <webroot>/usr/local/icecast/web</webroot>
+    </paths>
 
         <logging>
                 <accesslog>access.log</accesslog>

<p><p>1.8       +2 -2      icecast/src/Makefile.am

Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/Makefile.am,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- Makefile.am	9 Aug 2002 06:52:07 -0000	1.7
+++ Makefile.am	18 Aug 2002 05:06:58 -0000	1.8
@@ -8,10 +8,10 @@
 
 noinst_HEADERS = config.h os.h logging.h sighandler.h connection.h global.h\
          util.h slave.h source.h stats.h refbuf.h client.h format.h format_vorbis.h\
-	 compat.h format_mp3.h
+	 compat.h format_mp3.h fserve.h
 icecast_SOURCES = config.c main.c logging.c sighandler.c connection.c global.c\
          util.c slave.c source.c stats.c refbuf.c client.c format.c format_vorbis.c\
-	 format_mp3.c xslt.c
+	 format_mp3.c xslt.c fserve.c
     
 icecast_LDADD = net/libicenet.la thread/libicethread.la httpp/libicehttpp.la\
                 log/libicelog.la avl/libiceavl.la timing/libicetiming.la

<p><p>1.19      +6 -0      icecast/src/config.c

Index: config.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/config.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- config.c	16 Aug 2002 14:55:56 -0000	1.18
+++ config.c	18 Aug 2002 05:06:58 -0000	1.19
@@ -16,6 +16,7 @@
 #define CONFIG_DEFAULT_SOURCE_PASSWORD "changeme"
 #define CONFIG_DEFAULT_RELAY_PASSWORD "changeme"
 #define CONFIG_DEFAULT_ICE_LOGIN 0
+#define CONFIG_DEFAULT_FILESERVE 1
 #define CONFIG_DEFAULT_TOUCH_FREQ 5
 #define CONFIG_DEFAULT_HOSTNAME "localhost"
 #define CONFIG_DEFAULT_PORT 8888
@@ -162,6 +163,7 @@
         _configuration.source_password = CONFIG_DEFAULT_SOURCE_PASSWORD;
         _configuration.relay_password = CONFIG_DEFAULT_RELAY_PASSWORD;
         _configuration.ice_login = CONFIG_DEFAULT_ICE_LOGIN;
+	_configuration.fileserve = CONFIG_DEFAULT_FILESERVE;
         _configuration.touch_freq = CONFIG_DEFAULT_TOUCH_FREQ;
         _configuration.dir_list = NULL;
         _configuration.hostname = CONFIG_DEFAULT_HOSTNAME;
@@ -213,6 +215,10 @@
                 } else if (strcmp(node->name, "icelogin") == 0) {
                         tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
                         _configuration.ice_login = atoi(tmp);
+			if (tmp) xmlFree(tmp);
+		} else if (strcmp(node->name, "fileserve") == 0) {
+			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+			_configuration.fileserve = atoi(tmp);
                         if (tmp) xmlFree(tmp);
                 } else if (strcmp(node->name, "hostname") == 0) {
                         if (_configuration.hostname && _configuration.hostname != CONFIG_DEFAULT_HOSTNAME) xmlFree(_configuration.hostname);

<p><p>1.10      +1 -0      icecast/src/config.h

Index: config.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/config.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- config.h	16 Aug 2002 14:55:56 -0000	1.9
+++ config.h	18 Aug 2002 05:06:58 -0000	1.10
@@ -25,6 +25,7 @@
         int header_timeout;
         int source_timeout;
     int ice_login;
+    int fileserve;
 
         char *source_password;
     char *relay_password;

<p><p>1.27      +13 -0     icecast/src/connection.c

Index: connection.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/connection.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- connection.c	17 Aug 2002 08:32:15 -0000	1.26
+++ connection.c	18 Aug 2002 05:06:58 -0000	1.27
@@ -34,6 +34,7 @@
 #include "format.h"
 #include "logging.h"
 #include "xslt.h"
+#include "fserve.h"
 
 #include "source.h"
 
@@ -530,6 +531,18 @@
         free(fullpath);
         return;
         }
+    else if(config_get_config()->fileserve && 
+            stat(fullpath, &statbuf) == 0) {
+        client->respcode = 200;
+        bytes = sock_write(client->con->sock, 
+                "HTTP/1.0 200 OK\r\nContent-Type: %s\r\n\r\n", 
+                fserve_content_type(fullpath));
+        if(bytes > 0) client->con->sent_bytes = bytes;
+        if(fserve_client_create(client, fullpath) < 0)
+            client_destroy(client);
+        free(fullpath);
+        return;
+    }
     free(fullpath);
 
     if(strcmp(util_get_extension(uri), "m3u") == 0) {

<p><p>1.16      +4 -0      icecast/src/main.c

Index: main.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/main.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- main.c	13 Aug 2002 12:46:45 -0000	1.15
+++ main.c	18 Aug 2002 05:06:58 -0000	1.16
@@ -27,6 +27,7 @@
 #include "stats.h"
 #include "logging.h"
 #include "xslt.h"
+#include "fserve.h"
 
 #ifdef _WIN32
 #define snprintf _snprintf
@@ -53,10 +54,13 @@
         global_initialize();
         refbuf_initialize();
     xslt_initialize();
+    DEBUG0("Calling fserve_initialize()");
+    fserve_initialize();
 }
 
 static void _shutdown_subsystems(void)
 {
+    fserve_shutdown();
     xslt_shutdown();
         refbuf_shutdown();
         stats_shutdown();

<p><p>1.1                  icecast/src/fserve.c

Index: fserve.c
===================================================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#ifndef _WIN32
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#else
#include <winsock2.h>
#include <windows.h>
#endif

#include "thread.h"
#include "avl.h"
#include "httpp.h"
#include "sock.h"

#include "connection.h"
#include "global.h"
#include "refbuf.h"
#include "client.h"
#include "stats.h"
#include "format.h"
#include "log.h"
#include "logging.h"
#include "config.h"
#include "util.h"

#include "fserve.h"

#undef CATMODULE
#define CATMODULE "fserve"

#define BUFSIZE 4096

tatic avl_tree *client_tree;
static avl_tree *pending_tree;

tatic cond_t fserv_cond;
static thread_t *fserv_thread;
static int run_fserv;

/* avl tree helper */
static int _compare_clients(void *compare_arg, void *a, void *b);
static int _remove_client(void *key);
static int _free_client(void *key);
void *fserv_thread_function(void *arg);

void fserve_initialize(void)
{
    if(!config_get_config()->fileserve)
        return;

        client_tree = avl_tree_new(_compare_clients, NULL);
        pending_tree = avl_tree_new(_compare_clients, NULL);
    thread_cond_create(&fserv_cond);

    run_fserv = 1;

    fserv_thread = thread_create("File Serving Thread", 
            fserv_thread_function, NULL, THREAD_ATTACHED);
}

void fserve_shutdown(void)
{
    if(!config_get_config()->fileserve)
        return;

    run_fserv = 0;
    thread_cond_signal(&fserv_cond);
    thread_join(fserv_thread);

    thread_cond_destroy(&fserv_cond);
    avl_tree_free(client_tree, _free_client);
    avl_tree_free(pending_tree, _free_client);
}

void *fserv_thread_function(void *arg)
{
    avl_node *client_node, *pending_node;
    fserve_t *client;
    int sbytes, bytes;

    while (run_fserv) {
        avl_tree_rlock(client_tree);

        client_node = avl_get_first(client_tree);
        if(!client_node) {
            pending_node = avl_get_first(pending_tree);
            if(!pending_node) {
                /* There are no current clients. Wait until there are... */
                avl_tree_unlock(client_tree);
                thread_cond_wait(&fserv_cond);
                continue;
            }
        }

        while(client_node) {
            avl_node_wlock(client_node);

            client = (fserve_t *)client_node->key;

            if(client->offset >= client->datasize) {
                /* Grab a new chunk */
                bytes = fread(client->buf, 1, BUFSIZE, client->file);
                if(bytes <= 0) {
                    client->client->con->error = 1;
                    avl_node_unlock(client_node);
                    client_node = avl_get_next(client_node);
                    continue;
                }
                client->offset = 0;
                client->datasize = bytes;
            }

            /* Now try and send current chunk. */
            sbytes = sock_write_bytes(client->client->con->sock, 
                    &client->buf[client->offset], 
                    client->datasize - client->offset);

            // TODO: remove clients if they take too long.
            if(sbytes >= 0) {
                client->offset += sbytes;
                client->client->con->sent_bytes += sbytes;
            }
            else if(!sock_recoverable(sock_error())) {
                DEBUG0("Fileserving client had fatal error, disconnecting");
                client->client->con->error = 1;
            }
            else
                DEBUG0("Fileserving client had recoverable error");

            avl_node_unlock(client_node);
            client_node = avl_get_next(client_node);
        }

        avl_tree_unlock(client_tree);

        /* Now we need a write lock instead, to delete done clients. */
        avl_tree_wlock(client_tree);

        client_node = avl_get_first(client_tree);
        while(client_node) {
            client = (fserve_t *)client_node->key;
            if(client->client->con->error) {
                client_node = avl_get_next(client_node);
                avl_delete(client_tree, (void *)client, _free_client);
                continue;
            }
            client_node = avl_get_next(client_node);
        }

        avl_tree_wlock(pending_tree);

        /* And now insert new clients. */
        client_node = avl_get_first(pending_tree);
        while(client_node) {
            client = (fserve_t *)client_node->key;
            avl_insert(client_tree, client);
            client_node = avl_get_next(client_node);

        }

        /* clear pending */
        while(avl_get_first(pending_tree)) {
            avl_delete(pending_tree, avl_get_first(pending_tree)->key, 
                    _remove_client);
        }

        avl_tree_unlock(pending_tree);
        avl_tree_unlock(client_tree);
    }

    /* Shutdown path */

    avl_tree_wlock(pending_tree);
    while(avl_get_first(pending_tree))
        avl_delete(pending_tree, avl_get_first(pending_tree)->key, 
                _free_client);
    avl_tree_unlock(pending_tree);

    avl_tree_wlock(client_tree);
    while(avl_get_first(client_tree))
        avl_delete(client_tree, avl_get_first(client_tree)->key, 
                _free_client);
    avl_tree_unlock(client_tree);

    thread_exit(0);
    return NULL;
}

char *fserve_content_type(char *path)
{
    char *ext = util_get_extension(path);

    if(!strcmp(ext, "ogg"))
        return "application/x-ogg";
    else if(!strcmp(ext, "mp3"))
        return "audio/mpeg";
    else if(!strcmp(ext, "html"))
        return "text/html";
    else if(!strcmp(ext, "txt"))
        return "text/plain";
    else
        return "application/octet-stream";
    /* TODO Add more types */
}

tatic void fserve_client_destroy(fserve_t *client)
{
    if(client) {
        if(client->buf)
            free(client->buf);
        if(client->file)
            fclose(client->file);

        if(client->client)
            client_destroy(client->client);
        free(client);
    }
}

int fserve_client_create(client_t *httpclient, char *path)
{
    fserve_t *client = calloc(1, sizeof(fserve_t));

    client->client = httpclient;
    client->file = fopen(path, "rb");
    if(!client->file) {
        fserve_client_destroy(client);
        return -1;
    }
    client->offset = 0;
    client->datasize = 0;
    client->buf = malloc(BUFSIZE);

    avl_tree_wlock(pending_tree);
    avl_insert(pending_tree, client);
    avl_tree_unlock(pending_tree);

    thread_cond_signal(&fserv_cond);

    return 0;
}

tatic int _compare_clients(void *compare_arg, void *a, void *b)
{
        connection_t *cona = (connection_t *)a;
    connection_t *conb = (connection_t *)b;

        if (cona->id < conb->id) return -1;
        if (cona->id > conb->id) return 1;

        return 0;
}

tatic int _remove_client(void *key)
{
        return 1;
}

tatic int _free_client(void *key)
{
        fserve_t *client = (fserve_t *)key;

        fserve_client_destroy(client);
        
        return 1;
}

<p><p><p>1.1                  icecast/src/fserve.h

Index: fserve.h
===================================================================
#ifndef __FSERVE_H__
#define __FSERVE_H__

#include <stdio.h>

typedef struct
{
    client_t *client;

    FILE *file;
    int offset;
    int datasize;
    unsigned char *buf;
} fserve_t;

void fserve_initialize(void);
void fserve_shutdown(void);
char *fserve_content_type(char *path);
int fserve_client_create(client_t *httpclient, char *path);

<p>#endif

<p><p><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