Esempio n. 1
0
static int wait_for_fds(void)
{
    fserve_t *fclient;
    int ret;

    while (run_fserv)
    {
        /* add any new clients here */
        if (pending_list)
        {
            thread_spin_lock (&pending_lock);

            fclient = (fserve_t*)pending_list;
            while (fclient)
            {
                fserve_t *to_move = fclient;
                fclient = fclient->next;
                to_move->next = active_list;
                active_list = to_move;
                client_tree_changed = 1;
                fserve_clients++;
            }
            pending_list = NULL;
            thread_spin_unlock(&pending_lock);
        }
        /* drop out of here if someone is ready */
        ret = fserve_client_waiting();
        if (ret)
            return ret;
    }
    return -1;
}
Esempio n. 2
0
// write filename extension for matching mime type.
// lookup matching mime type and write extension into buffer space provided
void fserve_write_mime_ext (const char *mimetype, char *buf, unsigned int len)
{
    avl_node *node;
    int semi;

    if (mimetype == NULL || buf == NULL || len > 2000) return;
    semi = strcspn (mimetype, "; ");
    if (semi == 0) return;
    if (mimetype [semi])
    {
        char *mt = alloca (++semi);
        snprintf (mt, semi, "%s", mimetype);
        mimetype = (const char *)mt;
    }
    thread_spin_lock (&pending_lock);
    node = avl_get_first (mimetypes);
    while (node)
    {
       mime_type *mime = (mime_type *)node->key;
       if (mime && strcmp (mime->type, mimetype) == 0)
       {
           snprintf (buf, len, "%s", mime->ext);
           break;
       }
       node = avl_get_next (node);
    }
    thread_spin_unlock (&pending_lock);
}
Esempio n. 3
0
/* add client to connection queue. At this point some header information
 * has been collected, so we now pass it onto the connection thread for
 * further processing
 */
static void _add_connection (client_queue_t *node)
{
    thread_spin_lock (&_connection_lock);
    *_con_queue_tail = node;
    _con_queue_tail = (volatile client_queue_t **)&node->next;
    thread_spin_unlock (&_connection_lock);
}
Esempio n. 4
0
void fserve_shutdown(void)
{
    if (!__inited)
        return;

    thread_spin_lock (&pending_lock);
    run_fserv = 0;
    while (pending_list)
    {
        fserve_t *to_go = (fserve_t *)pending_list;
        pending_list = to_go->next;

        fserve_client_destroy (to_go);
    }
    while (active_list)
    {
        fserve_t *to_go = active_list;
        active_list = to_go->next;
        fserve_client_destroy (to_go);
    }

    if (mimetypes)
        avl_tree_free (mimetypes, _delete_mapping);

    thread_spin_unlock (&pending_lock);
    thread_spin_destroy (&pending_lock);
    ICECAST_LOG_INFO("file serving stopped");
}
Esempio n. 5
0
unsigned long global_getrate_avg (struct rate_calc *rate)
{
    unsigned long v;
    thread_spin_lock (&global.spinlock);
    v = rate_avg (rate);
    thread_spin_unlock (&global.spinlock);
    return v;
}
Esempio n. 6
0
static unsigned long _next_connection_id(void)
{
    unsigned long id;

    thread_spin_lock (&_connection_lock);
    id = _current_id++;
    thread_spin_unlock (&_connection_lock);

    return id;
}
Esempio n. 7
0
static uint64_t _next_connection_id(void)
{
    uint64_t id;

    thread_spin_lock (&_connection_lock);
    id = _current_id++;
    thread_spin_unlock (&_connection_lock);

    return id;
}
Esempio n. 8
0
/* called after each xml reload */
void stats_global (ice_config_t *config)
{
    stats_event_flags (NULL, "server_id", config->server_id, STATS_GENERAL);
    stats_event_flags (NULL, "host", config->hostname, STATS_GENERAL);
    stats_event (NULL, "location", config->location);
    stats_event (NULL, "admin", config->admin);
    thread_spin_lock (&global.spinlock);
    global.max_rate = config->max_bandwidth;
    throttle_sends = 0;
    thread_spin_unlock (&global.spinlock);
}
Esempio n. 9
0
int client_change_worker (client_t *client, worker_t *dest_worker)
{
    if (dest_worker->running == 0)
        return 0;
    client->next_on_worker = NULL;

    thread_spin_lock (&dest_worker->lock);
    worker_add_client (dest_worker, client);
    thread_spin_unlock (&dest_worker->lock);
    worker_wakeup (dest_worker);

    return 1;
}
Esempio n. 10
0
void client_add_incoming (client_t *client)
{
    worker_t *handler;

    thread_rwlock_rlock (&workers_lock);
    handler = worker_incoming;
    thread_spin_lock (&handler->lock);
    thread_rwlock_unlock (&workers_lock);

    worker_add_client (handler, client);
    thread_spin_unlock (&handler->lock);
    worker_wakeup (handler);
}
Esempio n. 11
0
/* Routine to actually add pre-configured client structure to pending list and
 * then to start off the file serving thread if it is not already running
 */
static void fserve_add_pending (fserve_t *fclient)
{
    thread_spin_lock (&pending_lock);
    fclient->next = (fserve_t *)pending_list;
    pending_list = fclient;
    if (run_fserv == 0)
    {
        run_fserv = 1;
        ICECAST_LOG_DEBUG("fserve handler waking up");
        thread_create("File Serving Thread", fserv_thread_function, NULL, THREAD_DETACHED);
    }
    thread_spin_unlock (&pending_lock);
}
Esempio n. 12
0
void client_add_worker (client_t *client)
{
    worker_t *handler;

    thread_rwlock_rlock (&workers_lock);
    /* add client to the handler with the least number of clients */
    handler = worker_selected();
    thread_spin_lock (&handler->lock);
    thread_rwlock_unlock (&workers_lock);

    worker_add_client (handler, client);
    thread_spin_unlock (&handler->lock);
    worker_wakeup (handler);
}
Esempio n. 13
0
int fserve_client_waiting(void)
{
    fserve_t *fclient;
    fd_set realfds;

    /* only rebuild fds if there are clients added/removed */
    if (client_tree_changed) {
        client_tree_changed = 0;
        FD_ZERO(&fds);
        fd_max = SOCK_ERROR;
        fclient = active_list;
        while (fclient) {
            FD_SET(fclient->client->con->sock, &fds);
            if (fclient->client->con->sock > fd_max || fd_max == SOCK_ERROR)
                fd_max = fclient->client->con->sock;
            fclient = fclient->next;
        }
    }
    /* hack for windows, select needs at least 1 descriptor */
    if (fd_max == SOCK_ERROR)
    {
        thread_spin_lock (&pending_lock);
        run_fserv = 0;
        thread_spin_unlock (&pending_lock);
        return -1;
    }
    else
    {
        struct timeval tv;
        tv.tv_sec = 0;
        tv.tv_usec = 200000;
        /* make a duplicate of the set so we do not have to rebuild it
         * each time around */
        memcpy(&realfds, &fds, sizeof(fd_set));
        if(select(fd_max+1, NULL, &realfds, NULL, &tv) > 0)
        {
            /* mark any clients that are ready */
            fclient = active_list;
            while (fclient)
            {
                if (FD_ISSET (fclient->client->con->sock, &realfds))
                    fclient->ready = 1;
                fclient = fclient->next;
            }
            return 1;
        }
    }
    return 0;
}
Esempio n. 14
0
/* thread to read xsl file and add to the cache */
void *xslt_update (void *arg)
{
    xsl_req *x = arg;
    client_t *client = x->client;
    char *fn = x->cache.filename;
    xsltStylesheetPtr sheet;

    xmlSetStructuredErrorFunc ("xsl/file", config_xml_parse_failure);
    xsltSetGenericErrorFunc ("", log_parse_failure);

    sheet = x->cache.stylesheet = xsltParseStylesheetFile (XMLSTR(fn));
    if (sheet)
    {
        int i;

        INFO1 ("loaded stylesheet %s", x->cache.filename);
        if (sheet->mediaType && strcmp ((char*)sheet->mediaType, "text/html") != 0)
        {
            // avoid this lookup for html pages
            const char _hdr[] = "Content-Disposition: attachment; filename=\"file.";
            const size_t _hdrlen = sizeof (_hdr);
            size_t len = _hdrlen + 12;
            char *filename = malloc (len); // enough for name and extension
            strcpy (filename, _hdr);
            fserve_write_mime_ext ((char*)sheet->mediaType, filename + _hdrlen - 1, len - _hdrlen - 4);
            strcat (filename, "\"\r\n");
            x->cache.disposition = filename;
        }
        // we now have a sheet, find and update.
        thread_rwlock_wlock (&xslt_lock);
        i = xslt_cached (fn, &x->cache, time(NULL));
        xslt_send_sheet (client, x->doc, i);
    }
    else
    {
        WARN1 ("problem reading stylesheet \"%s\"", x->cache.filename);
        free (fn);
        xmlFreeDoc (x->doc);
        free (x->cache.disposition);
        client->shared_data = NULL;
        client_send_404 (client, "Could not parse XSLT file");
    }
    thread_spin_lock (&update_lock);
    xsl_updating--;
    thread_spin_unlock (&update_lock);
    free (x);
    return NULL;
}
Esempio n. 15
0
/* string returned needs to be free'd */
char *fserve_content_type (const char *path)
{
    char *ext = util_get_extension(path);
    mime_type exttype = { NULL, NULL };
    void *result;
    char *type;

    if (ext == NULL)
        return strdup ("text/html");
    exttype.ext = strdup (ext);

    thread_spin_lock (&pending_lock);
    if (mimetypes && !avl_get_by_key (mimetypes, &exttype, &result))
    {
        mime_type *mime = result;
        free (exttype.ext);
        type = strdup (mime->type);
    }
    else {
        free (exttype.ext);
        /* Fallbacks for a few basic ones */
        if(!strcmp(ext, "ogg"))
            type = strdup ("application/ogg");
        else if(!strcmp(ext, "mp3"))
            type = strdup ("audio/mpeg");
        else if(!strcmp(ext, "html"))
            type = strdup ("text/html");
        else if(!strcmp(ext, "css"))
            type = strdup ("text/css");
        else if(!strcmp(ext, "txt"))
            type = strdup ("text/plain");
        else if(!strcmp(ext, "jpg"))
            type = strdup ("image/jpeg");
        else if(!strcmp(ext, "png"))
            type = strdup ("image/png");
        else if(!strcmp(ext, "m3u"))
            type = strdup ("audio/x-mpegurl");
        else if(!strcmp(ext, "aac"))
            type = strdup ("audio/aac");
        else
            type = strdup ("application/octet-stream");
    }
    thread_spin_unlock (&pending_lock);
    return type;
}
Esempio n. 16
0
/* this returns queued clients for the connection thread. headers are
 * already provided, but need to be parsed.
 */
static client_queue_t *_get_connection(void)
{
    client_queue_t *node = NULL;

    thread_spin_lock (&_connection_lock);

    if (_con_queue)
    {
        node = (client_queue_t *)_con_queue;
        _con_queue = node->next;
        if (_con_queue == NULL)
            _con_queue_tail = &_con_queue;
        node->next = NULL;
    }

    thread_spin_unlock (&_connection_lock);
    return node;
}
Esempio n. 17
0
int fserve_client_waiting (void)
{
    fserve_t *fclient;
    unsigned int i = 0;

    /* only rebuild ufds if there are clients added/removed */
    if (client_tree_changed) {
        struct pollfd *ufds_new = realloc(ufds, fserve_clients * sizeof(struct pollfd));
        /* REVIEW: If we can not allocate new ufds, keep old ones for now. */
        if (ufds_new || fserve_clients == 0) {
            ufds = ufds_new;
            client_tree_changed = 0;
            fclient = active_list;
            while (fclient)
            {
                ufds[i].fd = fclient->client->con->sock;
                ufds[i].events = POLLOUT;
                ufds[i].revents = 0;
                fclient = fclient->next;
                i++;
            }
        }
    }

    if (!ufds) {
        thread_spin_lock (&pending_lock);
        run_fserv = 0;
        thread_spin_unlock (&pending_lock);
        return -1;
    } else if (poll(ufds, fserve_clients, 200) > 0) {
        /* mark any clients that are ready */
        fclient = active_list;
        for (i=0; i<fserve_clients; i++)
        {
            if (ufds[i].revents & (POLLOUT|POLLHUP|POLLERR))
            fclient->ready = 1;
            fclient = fclient->next;
        }
        return 1;
    }

    return 0;
}
Esempio n. 18
0
void global_add_bitrates (struct rate_calc *rate, unsigned long value, uint64_t milli)
{
    float avg;
    thread_spin_lock (&global.spinlock);
    rate_add (rate, value, milli);
    avg = rate_avg (rate);

    if (global.max_rate)
    {
        float ratio = avg / global.max_rate;
        if (ratio > 0.99)
            throttle_sends = 3;
        else if (ratio > 0.9)
            throttle_sends = 2;
        else if (ratio > 0.8)
            throttle_sends = 1;
        else if (throttle_sends > 0)
            throttle_sends--;
    }
    thread_spin_unlock (&global.spinlock);
}
Esempio n. 19
0
/* thread to read xsl file and add to the cache */
void *xslt_update (void *arg)
{
    xsl_req *x = arg;
    client_t *client = x->client;
    worker_t *worker = client ? client->worker : NULL;
    char *fn = x->cache.filename;

    x->cache.stylesheet = xsltParseStylesheetFile (XMLSTR(fn));
    if (x->cache.stylesheet)
    {
        int i = x->index;

        if (client) fn = strdup (fn); // need to copy the filename if another lookup is to do
        INFO1 ("loaded stylesheet %s", x->cache.filename);
        thread_rwlock_wlock (&xslt_lock);
        free (cache[i].filename);
        xsltFreeStylesheet (cache[i].stylesheet);
        memcpy (&cache[i], &x->cache, sizeof (stylesheet_cache_t));
        thread_rwlock_unlock (&xslt_lock);
        memset (&x->cache, 0, sizeof (stylesheet_cache_t));

        if (client)
        {
            x->cache.filename = fn;
            client->flags |= CLIENT_ACTIVE;
        }
    }
    else
    {
        WARN1 ("problem reading stylesheet \"%s\"", x->cache.filename);
        free (fn);
        if (client) client_send_404 (client, "Could not parse XSLT file");
    }
    thread_spin_lock (&update_lock);
    xsl_updating--;
    thread_spin_unlock (&update_lock);
    if (worker) worker_wakeup (worker); // wakeup after the decrease or it may delay
    if (client == NULL) free (x);
    return NULL;
}
Esempio n. 20
0
static void worker_relocate_clients (worker_t *worker)
{
    if (workers == NULL)
        return;
    while (worker->count || worker->pending_count)
    {
        client_t *client = worker->clients, **prevp = &worker->clients;

        worker->wakeup_ms = worker->time_ms + 150;
        worker->current_time.tv_sec = (time_t)(worker->time_ms/1000);
        while (client)
        {
            if (client->flags & CLIENT_ACTIVE)
            {
                client->worker = workers;
                prevp = &client->next_on_worker;
            }
            else
            {
                *prevp = client->next_on_worker;
                worker_add_client (worker, client);
                worker->count--;
            }
            client = *prevp;
        }
        if (worker->clients)
        {
            thread_spin_lock (&workers->lock);
            *workers->pending_clients_tail = worker->clients;
            workers->pending_clients_tail = prevp;
            workers->pending_count += worker->count;
            thread_spin_unlock (&workers->lock);
            worker_wakeup (workers);
            worker->clients = NULL;
            worker->last_p = &worker->clients;
            worker->count = 0;
        }
        worker_wait (worker);
    }
}
Esempio n. 21
0
/* string returned needs to be free'd */
char *fserve_content_type (const char *path)
{
    char *ext = util_get_extension(path);
    mime_type exttype = { NULL, NULL };
    void *result;
    char *type;

    if (ext == NULL)
        return strdup ("text/html");
    exttype.ext = strdup (ext);

    thread_spin_lock (&pending_lock);
    if (mimetypes && !avl_get_by_key (mimetypes, &exttype, &result))
    {
        mime_type *mime = result;
        type = strdup (mime->type);
    }
    else
        type = strdup ("application/octet-stream");
    thread_spin_unlock (&pending_lock);
    free (exttype.ext);
    return type;
}
Esempio n. 22
0
void fserve_recheck_mime_types (ice_config_t *config)
{
    mime_type *mapping;
    int i;
    avl_tree *old_mimetypes = NULL, *new_mimetypes = avl_tree_new(_compare_mappings, NULL);

    mime_type defaults[] = {
        { "m3u",            "audio/x-mpegurl" },
        { "pls",            "audio/x-scpls" },
        { "xspf",           "application/xspf+xml" },
        { "ogg",            "application/ogg" },
        { "mp3",            "audio/mpeg" },
        { "aac",            "audio/aac" },
        { "aacp",           "audio/aacp" },
        { "css",            "text/css" },
        { "txt",            "text/plain" },
        { "html",           "text/html" },
        { "jpg",            "image/jpg" },
        { "png",            "image/png" },
        { "gif",            "image/gif" },
        { NULL, NULL }
    };

    for (i=0; defaults[i].ext; i++)
    {
        mapping = malloc (sizeof(mime_type));
        mapping->ext = strdup (defaults [i].ext);
        mapping->type = strdup (defaults [i].type);
        if (avl_insert (new_mimetypes, mapping) != 0)
            _delete_mapping (mapping);
    }
    do
    {
        char *type, *ext, *cur;
        FILE *mimefile = NULL;
        char line[4096];

        if (config->mimetypes_fn == NULL)
        {
            INFO0 ("no mime types file defined, using defaults");
            break;
        }
        mimefile = fopen (config->mimetypes_fn, "r");
        if (mimefile == NULL)
        {
            WARN1 ("Cannot open mime types file %s, using defaults", config->mimetypes_fn);
            break;
        }
        while (fgets(line, sizeof line, mimefile))
        {
            line[4095] = 0;

            if(*line == 0 || *line == '#')
                continue;

            type = line;
            cur = line;

            while(*cur != ' ' && *cur != '\t' && *cur)
                cur++;
            if(*cur == 0)
                continue;

            *cur++ = 0;

            while(1)
            {
                while(*cur == ' ' || *cur == '\t')
                    cur++;
                if(*cur == 0)
                    break;

                ext = cur;
                while(*cur != ' ' && *cur != '\t' && *cur != '\n' && *cur)
                    cur++;
                *cur++ = 0;
                if(*ext)
                {
                    void *tmp;
                    /* Add a new extension->type mapping */
                    mapping = malloc(sizeof(mime_type));
                    mapping->ext = strdup(ext);
                    mapping->type = strdup(type);
                    if (!avl_get_by_key (new_mimetypes, mapping, &tmp))
                        avl_delete (new_mimetypes, mapping, _delete_mapping);
                    if (avl_insert (new_mimetypes, mapping) != 0)
                        _delete_mapping (mapping);
                }
            }
        }
        fclose(mimefile);
    } while (0);

    thread_spin_lock (&pending_lock);
    old_mimetypes = mimetypes;
    mimetypes = new_mimetypes;
    thread_spin_unlock (&pending_lock);
    if (old_mimetypes)
        avl_tree_free (old_mimetypes, _delete_mapping);
}
Esempio n. 23
0
static int xslt_req_sheet (client_t *client, xmlDocPtr doc, const char *fn, int i)
{
    xsl_req     *x = client->shared_data;
    worker_t    *worker = client->worker;
    time_t      now = worker->current_time.tv_sec;
    struct stat file;

    // DEBUG4 ("idx %d, fn %s, check %ld/%ld", i, i==CACHESIZE?"XXX":cache[i].filename, (long)cache[i].next_check, now);
    while (i < CACHESIZE && i >= 0 && cache[i].filename && cache[i].next_check >= now)
    {
        thread_spin_lock (&update_lock);
        if (now == cache[i].next_check)
        {
            cache[i].next_check = now + 20;
            thread_spin_unlock (&update_lock);
            break; // jump out of loop to do xsl load
        }
        thread_spin_unlock (&update_lock);
        return i;
    }
    if (stat (fn, &file))
    {
        WARN2("Error checking for stylesheet file \"%s\": %s", fn, strerror(errno));
        return -1;
    }
    if (i < CACHESIZE && i >= 0)
    {
        thread_spin_lock (&update_lock);
        cache[i].next_check = now + 20;
        if (file.st_mtime == cache[i].last_modified)
        {
            thread_spin_unlock (&update_lock);
            DEBUG1 ("file %s has same mtime, not modified", cache[i].filename);
            return i;
        }
        thread_spin_unlock (&update_lock);
        // DEBUG3 ("idx %d, time is %ld, %ld", i, (long)(cache[i].last_modified), (long)file.st_mtime);
    }
    if (x == NULL)
    {
        x = calloc (1, sizeof (xsl_req));
        x->index = i;
        x->client = client;
        x->doc = doc;
        x->cache.filename = strdup (fn);
        x->cache.last_modified = file.st_mtime;
        x->cache.cache_age = now;
        x->cache.next_check = now + 20;
        client->shared_data = x;
        client->schedule_ms = worker->time_ms;
        client->ops = &xslt_ops;
    }

    thread_spin_lock (&update_lock);
    if (xsl_updating < 3)
    {
        xsl_updating++;
        thread_spin_unlock (&update_lock);
        client->flags &= ~CLIENT_ACTIVE;
        // DEBUG1 ("Starting update thread for %s", x->cache.filename);
        thread_create ("update xslt", xslt_update, x, THREAD_DETACHED);
        return CACHESIZE;
    }
    thread_spin_unlock (&update_lock);
    // DEBUG1 ("Delaying update thread for %s", x->cache.filename);
    client->schedule_ms += 10;
    if ((client->flags & CLIENT_ACTIVE) == 0)
    {
        client->flags |= CLIENT_ACTIVE;
        worker_wakeup (worker);
    }
    return CACHESIZE;
}
Esempio n. 24
0
void global_reduce_bitrate_sampling (struct rate_calc *rate)
{
    thread_spin_lock (&global.spinlock);
    rate_reduce (rate, 500);
    thread_spin_unlock (&global.spinlock);
}
Esempio n. 25
0
static int xslt_cached (const char *fn, client_t *client)
{
    worker_t *worker = client->worker;
    time_t now = worker->current_time.tv_sec, oldest = now;
    int evict = 0, i;
    struct stat file;

    for(i=0; i < CACHESIZE; i++)
    {
        if(cache[i].filename)
        {
#ifdef _WIN32
            if (stricmp(fn, cache[i].filename) == 0)
#else
            if (strcmp(fn, cache[i].filename) == 0)
#endif
            {
                if (now - cache[i].last_checked > 10)
                {
                    cache[i].last_checked = now;
                    if (stat (fn, &file))
                    {
                        WARN2("Error checking for stylesheet file \"%s\": %s", fn, strerror(errno));
                        return i;
                    }
                    DEBUG1 ("rechecked file time on %s", fn);

                    thread_spin_lock (&update_lock);
                    if (file.st_mtime > cache[i].last_modified)
                    {
                        cache[i].last_modified = file.st_mtime;
                        thread_spin_unlock (&update_lock);
                        break;
                    }
                }
                thread_spin_unlock (&update_lock);
                cache[i].cache_age = now;
                return i;
            }
            if (oldest < cache[i].cache_age)
                continue;
        }
        evict = i;
    }
    xsl_req *x = calloc (1, sizeof (xsl_req));
    if (i < CACHESIZE)
    {
        x->index = i;
    }
    else
    {
        if (stat (fn, &file))
        {
            WARN2("Error checking for stylesheet file \"%s\": %s", fn, strerror(errno));
            free (x);
            return -2;
        }
        x->client = client;
        x->index = evict;
    }
    x->doc = client->shared_data;
    x->cache.filename = strdup (fn);
    x->cache.last_modified = file.st_mtime;
    x->cache.cache_age = now;
    x->cache.last_checked = now;
    client->shared_data = x;
    client->schedule_ms = worker->time_ms;
    client->ops = &xslt_ops;

    thread_spin_lock (&update_lock);
    if (xsl_updating < 3)
    {
        xsl_updating++;
        thread_spin_unlock (&update_lock);
        if (x->client)   client->flags &= ~CLIENT_ACTIVE;
        thread_create ("update xslt", xslt_update, x, THREAD_DETACHED);
        if (x->client == NULL)   return i;
    }
    else
    {
        thread_spin_unlock (&update_lock);
        x->client = client;
        client->schedule_ms += 10;
        if ((client->flags & CLIENT_ACTIVE) == 0)
        {
            client->flags |= CLIENT_ACTIVE;
            worker_wakeup (worker);
        }
    }
    return -1;
}
Esempio n. 26
0
void fserve_recheck_mime_types(ice_config_t *config)
{
    FILE *mimefile;
    char line[4096];
    char *type, *ext, *cur;
    mime_type *mapping;
    avl_tree *new_mimetypes;

    if (config->mimetypes_fn == NULL)
        return;
    mimefile = fopen (config->mimetypes_fn, "r");
    if (mimefile == NULL)
    {
        ICECAST_LOG_WARN("Cannot open mime types file %s", config->mimetypes_fn);
        return;
    }

    new_mimetypes = avl_tree_new(_compare_mappings, NULL);

    while(fgets(line, 4096, mimefile))
    {
        line[4095] = 0;

        if(*line == 0 || *line == '#')
            continue;

        type = line;

        cur = line;

        while(*cur != ' ' && *cur != '\t' && *cur)
            cur++;
        if(*cur == 0)
            continue;

        *cur++ = 0;

        while(1) {
            while(*cur == ' ' || *cur == '\t')
                cur++;
            if(*cur == 0)
                break;

            ext = cur;
            while(*cur != ' ' && *cur != '\t' && *cur != '\n' && *cur)
                cur++;
            *cur++ = 0;
            if(*ext)
            {
                void *tmp;
                /* Add a new extension->type mapping */
                mapping = malloc(sizeof(mime_type));
                mapping->ext = strdup(ext);
                mapping->type = strdup(type);
                if (!avl_get_by_key (new_mimetypes, mapping, &tmp))
                    avl_delete (new_mimetypes, mapping, _delete_mapping);
                avl_insert (new_mimetypes, mapping);
            }
        }
    }
    fclose(mimefile);

    thread_spin_lock (&pending_lock);
    if (mimetypes)
        avl_tree_free (mimetypes, _delete_mapping);
    mimetypes = new_mimetypes;
    thread_spin_unlock (&pending_lock);
}
Esempio n. 27
0
static void *start_relay_stream (void *arg)
{
    client_t *client = arg;
    relay_server *relay;
    source_t *src;
    int failed = 1, sources;

    global_lock();
    sources = ++global.sources;
    stats_event_args (NULL, "sources", "%d", global.sources);
    global_unlock();
    /* set the start time, because we want to decrease the sources on all failures */
    client->connection.con_time = time (NULL);
    do
    {
        ice_config_t *config = config_get_config();
        mount_proxy *mountinfo;

        relay = client->shared_data;
        src = relay->source;

        thread_rwlock_wlock (&src->lock);
        src->flags |= SOURCE_PAUSE_LISTENERS;
        if (sources > config->source_limit)
        {
            config_release_config();
            WARN1 ("starting relayed mountpoint \"%s\" requires a higher sources limit", relay->localmount);
            break;
        }
        config_release_config();
        INFO1("Starting relayed source at mountpoint \"%s\"", relay->localmount);

        if (open_relay (relay) < 0)
            break;
        if (connection_complete_source (src) < 0)
        {
            WARN1 ("Failed to complete initialisation on %s", relay->localmount);
            break;
        }
        stats_event_inc (NULL, "source_relay_connections");
        source_init (src);
        config = config_get_config();
        mountinfo = config_find_mount (config, src->mount);
        source_update_settings (config, src, mountinfo);
        INFO1 ("source %s is ready to start", src->mount);
        config_release_config();
        failed = 0;
    } while (0);

    client->ops = &relay_client_ops;
    client->schedule_ms = timing_get_time();

    if (failed)
    {
        /* failed to start any connection, better clean up and reset */
        if (relay->on_demand == 0)
        {
            yp_remove (relay->localmount);
            src->yp_public = -1;
        }
        relay->in_use = NULL;
        INFO2 ("listener count remaining on %s is %d", src->mount, src->listeners);
        src->flags &= ~(SOURCE_PAUSE_LISTENERS|SOURCE_RUNNING);
    }
    thread_rwlock_unlock (&src->lock);

    thread_spin_lock (&relay_start_lock);
    relays_connecting--;
    thread_spin_unlock (&relay_start_lock);

    client->flags |= CLIENT_ACTIVE;
    worker_wakeup (client->worker);
    return NULL;
}