Exemple #1
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;
}
Exemple #2
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;
}
Exemple #3
0
int fserve_setup_client_fb (client_t *client, fbinfo *finfo)
{
    fh_node *fh = &no_file;
    int ret = 0;

    if (finfo)
    {
        mount_proxy *minfo;
        if (finfo->flags & FS_FALLBACK && finfo->limit == 0)
            return -1;
        avl_tree_wlock (fh_cache);
        fh = find_fh (finfo);
        minfo = config_find_mount (config_get_config(), finfo->mount);
        if (fh)
        {
            thread_mutex_lock (&fh->lock);
            avl_tree_unlock (fh_cache);
            client->shared_data = NULL;
            if (minfo)
            {
                if (minfo->max_listeners >= 0 && fh->refcount > minfo->max_listeners)
                {
                    thread_mutex_unlock (&fh->lock);
                    config_release_config();
                    return client_send_403redirect (client, finfo->mount, "max listeners reached");
                }
                if (check_duplicate_logins (finfo->mount, fh->clients, client, minfo->auth) == 0)
                {
                    thread_mutex_unlock (&fh->lock);
                    config_release_config();
                    return client_send_403 (client, "Account already in use");
                }
            }
            config_release_config();
        }
        else
        {
            if (minfo && minfo->max_listeners == 0)
            {
                avl_tree_unlock (fh_cache);
                config_release_config();
                client->shared_data = NULL;
                return client_send_403redirect (client, finfo->mount, "max listeners reached");
            }
            config_release_config();
            fh = open_fh (finfo);
            if (fh == NULL)
                return client_send_404 (client, NULL);
            if (fh->finfo.limit)
                DEBUG2 ("request for throttled file %s (bitrate %d)", fh->finfo.mount, fh->finfo.limit*8);
        }
        if (fh->finfo.limit)
        {
            client->timer_start = client->worker->current_time.tv_sec;
            if (client->connection.sent_bytes == 0)
                client->timer_start -= 2;
            client->counter = 0;
            global_reduce_bitrate_sampling (global.out_bitrate);
        }
    }
    else
    {
        if (client->mount && (client->flags & CLIENT_AUTHENTICATED) && (client->respcode >= 300 || client->respcode < 200))
        {
            fh = calloc (1, sizeof (no_file));
            fh->finfo.mount = strdup (client->mount);
            fh->finfo.flags |= FS_DELETE;
            fh->refcount = 1;
            fh->f = SOCK_ERROR;
            thread_mutex_create (&fh->lock);
        }
        thread_mutex_lock (&fh->lock);
    }
    client->mount = fh->finfo.mount;
    if (fh->finfo.type == FORMAT_TYPE_UNDEFINED)
    {
        if (client->respcode == 0)
        {
            client->refbuf->len = 0;
            ret = format_general_headers (fh->format, client);
        }
    }
    else
    {
        if (fh->format->create_client_data && client->format_data == NULL)
            ret = fh->format->create_client_data (fh->format, client);
        if (fh->format->write_buf_to_client)
            client->check_buffer = fh->format->write_buf_to_client;
    }
    if (ret < 0)
    {
        thread_mutex_unlock (&fh->lock);
        return client_send_416 (client);
    }
    fh_add_client (fh, client);
    thread_mutex_unlock (&fh->lock);
    client->shared_data = fh;

    if (client->check_buffer == NULL)
        client->check_buffer = format_generic_write_to_client;

    client->ops = &buffer_content_ops;
    client->flags &= ~CLIENT_HAS_INTRO_CONTENT;
    client->flags |= CLIENT_IN_FSERVE;
    if (client->flags & CLIENT_ACTIVE)
    {
        client->schedule_ms = client->worker->time_ms;
        if (finfo && finfo->flags & FS_FALLBACK)
            return 0; // prevent a recursive loop 
        return client->ops->process (client);
    }
    else
    {
        worker_t *worker = client->worker;
        ret = (fh->finfo.limit) ? 0 : -1;
        client->flags |= CLIENT_ACTIVE;
        worker_wakeup (worker); /* worker may of already processed client but make sure */
    }
    return ret;
}
Exemple #4
0
static int command_manage_relay (client_t *client, int response)
{
    const char *relay_mount, *enable;
    const char *msg;
    relay_server *relay;
    xmlDocPtr doc;
    xmlNodePtr node;

    COMMAND_OPTIONAL (client, "relay", relay_mount);
    COMMAND_OPTIONAL (client, "enable", enable);

    if (relay_mount == NULL || enable == NULL)
    {
        avl_node *relaynode;
        doc = xmlNewDoc (XMLSTR("1.0"));
        node = xmlNewDocNode (doc, NULL, XMLSTR("icerelaystats"), NULL);
        xmlDocSetRootElement(doc, node);
        avl_tree_rlock (global.relays);
        relaynode = avl_get_first (global.relays);
        while (relaynode)
        {
            relay_server *relay = (relay_server*)relaynode->key;
            add_relay_xmlnode (node, relay);
            relaynode = avl_get_next (relaynode);
        }

        avl_tree_unlock (global.relays);
        return admin_send_response (doc, client, response, "managerelays.xsl");
    }

    avl_tree_rlock (global.relays);

    relay = slave_find_relay (relay_mount);
    msg = "no such relay";
    if (relay)
    {
        source_t *source = relay->source;
        client_t *client;

        thread_rwlock_wlock (&source->lock);
        client = source->client;
        if (atoi (enable))
            relay->flags |= RELAY_RUNNING;
        else
            relay->flags &= ~RELAY_RUNNING;
        if (client)
        {
            client->schedule_ms = 0;
            worker_wakeup (client->worker);
        }
        thread_rwlock_unlock (&source->lock);
        msg = "relay has been changed";
    }
    avl_tree_unlock (global.relays);

    doc = xmlNewDoc(XMLSTR("1.0"));
    node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL);
    xmlDocSetRootElement(doc, node);
    xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR(msg));
    xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1"));
    return admin_send_response(doc, client, response, "response.xsl");
}