Пример #1
0
static char *_get_stats(const char *source, const char *name)
{
    stats_node_t *stats = NULL;
    stats_source_t *src = NULL;
    char *value = NULL;

    if (source == NULL) {
        avl_tree_rlock (_stats.global_tree);
        stats = _find_node(_stats.global_tree, name);
        if (stats) value = (char *)strdup(stats->value);
        avl_tree_unlock (_stats.global_tree);
    } else {
        avl_tree_rlock (_stats.source_tree);
        src = _find_source(_stats.source_tree, source);
        if (src)
        {
            avl_tree_rlock (src->stats_tree);
            avl_tree_unlock (_stats.source_tree);
            stats = _find_node(src->stats_tree, name);
            if (stats) value = (char *)strdup(stats->value);
            avl_tree_unlock (src->stats_tree);
        }
        else
            avl_tree_unlock (_stats.source_tree);
    }

    return value;
}
Пример #2
0
/* This removes any source stats from virtual mountpoints, ie mountpoints
 * where no source_t exists. This function requires the global sources lock
 * to be held before calling.
 */
void stats_clear_virtual_mounts (void)
{
    avl_node *snode;

    avl_tree_wlock (_stats.source_tree);
    snode = avl_get_first(_stats.source_tree);
    while (snode)
    {
        stats_source_t *src = (stats_source_t *)snode->key;
        source_t *source = source_find_mount_raw (src->source);

        if (source == NULL)
        {
            stats_node_t *node;
            avl_tree_wlock (src->stats_tree);
            node = _find_node (src->stats_tree, "fallback");
            if (node == NULL)
            {
                /* no source_t and no fallback file stat, so delete */
                snode = avl_get_next (snode);
                avl_delete (_stats.source_tree, src, _free_source_stats);
                continue;
            }
            avl_tree_unlock (src->stats_tree);
        }

        snode = avl_get_next (snode);
    }
    avl_tree_unlock (_stats.source_tree);
}
Пример #3
0
void *my_calloc (const char *file, int line, size_t num, size_t size)
{
    alloc_node match, *result;
    snprintf (match.name, sizeof (match.name), "%s:%d", file, line);

    avl_tree_wlock (global.alloc_tree);
    if (avl_get_by_key (global.alloc_tree, &match, (void**)&result) == 0)
    {
        allocheader *block = calloc (1, (num*size)+sizeof(allocheader));
        result->count++;
        result->allocated += (num*size);
        block->info = result;
        block->len = num*size;
        avl_tree_unlock (global.alloc_tree);
        return block+1;
    }
    result = calloc (1, sizeof(alloc_node));
    if (result)
    {
        allocheader *block = calloc (1, (num*size)+sizeof(allocheader));
        snprintf (result->name, sizeof (result->name), "%s:%d", file, line);
        result->count = 1;
        result->allocated = (num * size);
        avl_insert (global.alloc_tree, result);
        block->info = result;
        block->len = num*size;
        avl_tree_unlock (global.alloc_tree);
        return block+1;
    }
    avl_tree_unlock (global.alloc_tree);
    return NULL;
}
Пример #4
0
int fserve_kill_client (client_t *client, const char *mount, int response)
{
    int loop = 2, id;
    fbinfo finfo;
    xmlDocPtr doc;
    xmlNodePtr node;
    const char *idtext, *v = "0";
    char buf[50];

    finfo.flags = 0;
    finfo.mount = (char*)mount;
    finfo.limit = 0;
    finfo.fallback = NULL;

    idtext = httpp_get_query_param (client->parser, "id");
    if (idtext == NULL)
        return client_send_400 (client, "missing parameter id");

    id = atoi(idtext);

    doc = xmlNewDoc(XMLSTR("1.0"));
    node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL);
    xmlDocSetRootElement(doc, node);
    snprintf (buf, sizeof(buf), "Client %d not found", id);

    avl_tree_rlock (fh_cache);
    while (1)
    {
        avl_node *node;
        fh_node *fh = find_fh (&finfo);
        if (fh)
        {
            thread_mutex_lock (&fh->lock);
            avl_tree_unlock (fh_cache);
            node = avl_get_first (fh->clients);
            while (node)
            {
                client_t *listener = (client_t *)node->key;
                if (listener->connection.id == id)
                {
                    listener->connection.error = 1;
                    snprintf (buf, sizeof(buf), "Client %d removed", id);
                    v = "1";
                    loop = 0;
                    break;
                }
                node = avl_get_next (node);
            }
            thread_mutex_unlock (&fh->lock);
            avl_tree_rlock (fh_cache);
        }
        if (loop == 0) break;
        loop--;
        if (loop == 1) finfo.flags = FS_FALLBACK;
    }
    avl_tree_unlock (fh_cache);
    xmlNewChild (node, NULL, XMLSTR("message"), XMLSTR(buf));
    xmlNewChild (node, NULL, XMLSTR("return"), XMLSTR(v));
    return admin_send_response (doc, client, response, "response.xsl");
}
Пример #5
0
int fserve_list_clients_xml (xmlNodePtr parent, fbinfo *finfo)
{
    int ret = 0;
    fh_node *fh;
    avl_node *anode;

    avl_tree_rlock (fh_cache);
    fh = find_fh (finfo);
    if (fh == NULL)
    {
        avl_tree_unlock (fh_cache);
        return 0;
    }
    thread_mutex_lock (&fh->lock);
    avl_tree_unlock (fh_cache);

    anode = avl_get_first (fh->clients);
    while (anode)
    {
        client_t *listener = (client_t *)anode->key;

        stats_listener_to_xml (listener, parent);
        ret++;
        anode = avl_get_next (anode);
    }
    thread_mutex_unlock (&fh->lock);
    return ret;
}
Пример #6
0
/* 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_authenticated_listener (const char *mount, mount_proxy *mountinfo, client_t *client)
{
    int ret = 0;
    source_t *source = NULL;

    client->authenticated = 1;

    /* Here we are parsing the URI request to see if the extension is .xsl, if
     * so, then process this request as an XSLT request
     */
    if (util_check_valid_extension (mount) == XSLT_CONTENT)
    {
        /* If the file exists, then transform it, otherwise, write a 404 */
        ICECAST_LOG_DEBUG("Stats request, sending XSL transformed stats");
        stats_transform_xslt (client, mount);
        return 0;
    }

    avl_tree_rlock (global.source_tree);
    source = source_find_mount (mount);

    if (source)
    {
        if (mountinfo)
        {
            if (check_duplicate_logins (source, client, mountinfo->auth) == 0)
            {
                avl_tree_unlock (global.source_tree);
                return -1;
            }

            /* set a per-mount disconnect time if auth hasn't set one already */
            if (mountinfo->max_listener_duration && client->con->discon_time == 0)
                client->con->discon_time = time(NULL) + mountinfo->max_listener_duration;
        }

        ret = add_listener_to_source (source, client);
        avl_tree_unlock (global.source_tree);
        if (ret == 0)
            ICECAST_LOG_DEBUG("client authenticated, passed to source");
    }
    else
    {
        avl_tree_unlock (global.source_tree);
        fserve_client_create (client, mount);
    }
    return ret;
}
Пример #7
0
int command_list_mounts(client_t *client, int response)
{
    DEBUG0("List mounts request");

    client_set_queue (client, NULL);
    client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE);
    if (response == TEXT)
    {
        redirector_update (client);

        snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
                "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
        client->refbuf->len = strlen (client->refbuf->data);
        client->respcode = 200;

        if (strcmp (httpp_getvar (client->parser, HTTPP_VAR_URI), "/admin/streams") == 0)
            client->refbuf->next = stats_get_streams (1);
        else
            client->refbuf->next = stats_get_streams (0);
        return fserve_setup_client (client);
    }
    else
    {
        xmlDocPtr doc;
        avl_tree_rlock (global.source_tree);
        doc = admin_build_sourcelist(NULL);
        avl_tree_unlock (global.source_tree);

        return admin_send_response (doc, client, response, "listmounts.xsl");
    }
}
Пример #8
0
long stats_handle (const char *mount)
{
    stats_source_t *src_stats;

    if (mount == NULL)
        return 0;
    avl_tree_wlock (_stats.source_tree);
    src_stats = _find_source(_stats.source_tree, mount);
    if (src_stats == NULL)
    {
        src_stats = (stats_source_t *)calloc (1, sizeof (stats_source_t));
        if (src_stats == NULL)
            abort();
        DEBUG1 ("new source stat %s", mount);
        src_stats->source = (char *)strdup (mount);
        src_stats->stats_tree = avl_tree_new (_compare_stats, NULL);
        src_stats->flags = STATS_SLAVE|STATS_GENERAL|STATS_HIDDEN;

        avl_insert (_stats.source_tree, (void *)src_stats);
    }
    avl_tree_wlock (src_stats->stats_tree);
    avl_tree_unlock (_stats.source_tree);

    return (long)src_stats;
}
Пример #9
0
void stats_global_calc (void)
{
    stats_event_t event;
    avl_node *anode;
    char buffer [VAL_BUFSIZE];

    connection_stats ();
    avl_tree_rlock (_stats.global_tree);
    anode = avl_get_first(_stats.global_tree);
    while (anode)
    {
        stats_node_t *node = (stats_node_t *)anode->key;

        if (node->flags & STATS_REGULAR)
            stats_listener_send (node->flags, "EVENT global %s %s\n", node->name, node->value);
        anode = avl_get_next (anode);
    }
    avl_tree_unlock (_stats.global_tree);
    build_event (&event, NULL, "outgoing_kbitrate", buffer);
    event.flags = STATS_COUNTERS|STATS_HIDDEN;

    snprintf (buffer, sizeof(buffer), "%" PRIu64,
            (int64_t)global_getrate_avg (global.out_bitrate) * 8 / 1024);
    process_event (&event);
}
Пример #10
0
static int command_alloc(client_t *client)
{
    xmlDocPtr doc = xmlNewDoc (XMLSTR("1.0"));
    xmlNodePtr rootnode = xmlNewDocNode(doc, NULL, XMLSTR("icestats"), NULL);
    avl_node *node;

    xmlDocSetRootElement(doc, rootnode);
    avl_tree_rlock (global.alloc_tree);
    node = avl_get_first (global.alloc_tree);
    while (node)
    {
        alloc_node *an = node->key;
        char value[25];
        xmlNodePtr bnode = xmlNewChild (rootnode, NULL, XMLSTR("block"), NULL);
        xmlSetProp (bnode, XMLSTR("name"), XMLSTR(an->name));
        snprintf (value, sizeof value, "%d", an->count);
        xmlNewChild (bnode, NULL, XMLSTR("count"), XMLSTR(value));
        snprintf (value, sizeof value, "%d", an->allocated);
        xmlNewChild (bnode, NULL, XMLSTR("allocated"), XMLSTR(value));

        node = avl_get_next (node);
    }
    avl_tree_unlock (global.alloc_tree);

    return admin_send_response (doc, client, RAW, "stats.xsl");
}
Пример #11
0
static void command_list_mounts(client_t *client, int response)
{
    DEBUG0("List mounts request");

    if (response == PLAINTEXT)
    {
        snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
                "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
        client->refbuf->len = strlen (client->refbuf->data);
        client->respcode = 200;

        client->refbuf->next = stats_get_streams ();
        fserve_add_client (client, NULL);
    }
    else
    {
        xmlDocPtr doc;
        avl_tree_rlock (global.source_tree);
        doc = admin_build_sourcelist(NULL);
        avl_tree_unlock (global.source_tree);

        admin_send_response(doc, client, response, 
            LISTMOUNTS_TRANSFORMED_REQUEST);
        xmlFreeDoc(doc);
    }
}
Пример #12
0
int fserve_query_count (fbinfo *finfo)
{
    int ret = -1;
    fh_node *fh;

    if (finfo->flags & FS_FALLBACK && finfo->limit)
    {
        avl_tree_wlock (fh_cache);
        fh = open_fh (finfo);
        if (fh)
        {
            ret = fh->refcount;
            thread_mutex_unlock (&fh->lock);
        }
    }
    else
    {
        avl_tree_rlock (fh_cache);
        fh = find_fh (finfo);
        if (fh)
        {
            thread_mutex_lock (&fh->lock);
            ret = fh->refcount;
            thread_mutex_unlock (&fh->lock);
        }
        avl_tree_unlock (fh_cache);
    }
    return ret;
}
Пример #13
0
static xmlNodePtr _dump_stats_to_doc (xmlNodePtr root, const char *show_mount, int flags)
{
    avl_node *avlnode;
    xmlNodePtr ret = NULL;

    /* general stats first */
    avl_tree_rlock (_stats.global_tree);
    avlnode = avl_get_first(_stats.global_tree);
    while (avlnode)
    {
        stats_node_t *stat = avlnode->key;
        if (stat->flags & flags)
            xmlNewTextChild (root, NULL, XMLSTR(stat->name), XMLSTR(stat->value));
        avlnode = avl_get_next (avlnode);
    }
    avl_tree_unlock (_stats.global_tree);
    /* now per mount stats */
    avl_tree_rlock (_stats.source_tree);
    avlnode = avl_get_first(_stats.source_tree);
    while (avlnode)
    {
        stats_source_t *source = (stats_source_t *)avlnode->key;
        if (((flags&STATS_HIDDEN) || (source->flags&STATS_HIDDEN) == (flags&STATS_HIDDEN)) &&
                (show_mount == NULL || strcmp (show_mount, source->source) == 0))
        {
            avl_node *avlnode2;
            xmlNodePtr xmlnode = xmlNewTextChild (root, NULL, XMLSTR("source"), NULL);
            avl_tree_rlock (source->stats_tree);
            avlnode2 = avl_get_first (source->stats_tree);

            xmlSetProp (xmlnode, XMLSTR("mount"), XMLSTR(source->source));
            if (ret == NULL)
                ret = xmlnode;
            while (avlnode2)
            {
                stats_node_t *stat = avlnode2->key;
                if ((flags&STATS_HIDDEN) || (stat->flags&STATS_HIDDEN) == (flags&STATS_HIDDEN))
                    xmlNewTextChild (xmlnode, NULL, XMLSTR(stat->name), XMLSTR(stat->value));
                avlnode2 = avl_get_next (avlnode2);
            }
            avl_tree_unlock (source->stats_tree);
        }
        avlnode = avl_get_next (avlnode);
    }
    avl_tree_unlock (_stats.source_tree);
    return ret;
}
Пример #14
0
int fserve_set_override (const char *mount, const char *dest, format_type_t type)
{
    fh_node fh, *result;

    fh.finfo.flags = FS_FALLBACK;
    fh.finfo.mount = (char *)mount;
    fh.finfo.fallback = NULL;
    fh.finfo.type = type;

    avl_tree_wlock (fh_cache);
    result = find_fh (&fh.finfo);
    if (result)
    {
        thread_mutex_lock (&result->lock);

        if (result->refcount > 0)
        {
            fh_node *copy = calloc (1, sizeof (*copy));
            avl_delete (fh_cache, result, NULL);
            copy->finfo = result->finfo;
            copy->finfo.mount = strdup (copy->finfo.mount);
            copy->prev_count = -1; // trigger stats update
            copy->expire = (time_t)-1;
            copy->stats = result->stats;
            copy->format = result->format;
            copy->f = result->f;
            thread_mutex_create (&copy->lock);
            copy->out_bitrate = rate_setup (10000, 1000);
            copy->clients = avl_tree_new (client_compare, NULL);
            avl_insert (fh_cache, copy);

            result->finfo.flags |= FS_DELETE;
            result->finfo.flags &= ~FS_FALLBACK;
            result->format = NULL;
            result->stats = 0;
            result->f = SOCK_ERROR;
            result->finfo.fallback = strdup (dest);
            result->finfo.type = type;
        }
        avl_tree_unlock (fh_cache);
        thread_mutex_unlock (&result->lock);
        INFO2 ("move clients from %s to %s", mount, dest);
        return 1;
    }
    avl_tree_unlock (fh_cache);
    return 0;
}
Пример #15
0
int admin_mount_request (client_t *client, const char *uri)
{
    source_t *source;
    const char *mount = httpp_get_query_param (client->parser, "mount");

    struct admin_command *cmd = find_admin_command (admin_mount, uri);

    if (cmd == NULL)
        return command_stats (client, uri);

    if (cmd == NULL || cmd->handle.source == NULL)
    {
        INFO0("mount request not recognised");
        return client_send_400 (client, "unknown request");
    }

    avl_tree_rlock(global.source_tree);
    source = source_find_mount_raw(mount);

    if (source == NULL)
    {
        avl_tree_unlock(global.source_tree);
        if (strncmp (cmd->request, "stats", 5) == 0)
            return command_stats (client, uri);
        if (strncmp (cmd->request, "listclients", 11) == 0)
            return fserve_list_clients (client, mount, cmd->response, 1);
        if (strncmp (cmd->request, "killclient", 10) == 0)
            return fserve_kill_client (client, mount, cmd->response);
        WARN1("Admin command on non-existent source %s", mount);
        return client_send_400 (client, "Source does not exist");
    }
    else
    {
        int ret = 0;
        thread_mutex_lock (&source->lock);
        if (source_available (source) == 0)
        {
            thread_mutex_unlock (&source->lock);
            avl_tree_unlock (global.source_tree);
            INFO1("Received admin command on unavailable mount \"%s\"", mount);
            return client_send_400 (client, "Source is not available");
        }
        ret = cmd->handle.source (client, source, cmd->response);
        avl_tree_unlock(global.source_tree);
        return ret;
    }
}
Пример #16
0
static void command_list_mounts(client_t *client, int response)
{
    DEBUG0("List mounts request");

    avl_tree_rlock (global.source_tree);
    if (response == PLAINTEXT)
    {
        char buffer [4096], *buf = buffer;
        unsigned int remaining = sizeof (buffer);
        int ret = snprintf (buffer, remaining,
                "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");

        avl_node *node = avl_get_first(global.source_tree);
        while (node && ret > 0 && (unsigned)ret < remaining)
        {
            source_t *source = (source_t *)node->key;
            node = avl_get_next(node);
            if (source->hidden)
                continue;
            remaining -= ret;
            buf += ret;
            ret = snprintf (buf, remaining, "%s\n", source->mount);
        }
        avl_tree_unlock (global.source_tree);
        /* handle last line */
        if (ret > 0 && (unsigned)ret < remaining)
        {
            remaining -= ret;
            buf += ret;
        }
        sock_write_bytes (client->con->sock, buffer, sizeof (buffer)-remaining);
    }
    else
    {
        xmlDocPtr doc = admin_build_sourcelist(NULL);
        avl_tree_unlock (global.source_tree);

        admin_send_response(doc, client, response, 
            LISTMOUNTS_TRANSFORMED_REQUEST);
        xmlFreeDoc(doc);
    }
    client_destroy(client);

    return;
}
Пример #17
0
client_t *source_find_client(source_t *source, int id)
{
    client_t fakeclient;
    void *result;
    connection_t fakecon;

    fakeclient.con = &fakecon;
    fakeclient.con->id = id;

    avl_tree_rlock(source->client_tree);
    if(avl_get_by_key(source->client_tree, &fakeclient, &result) == 0)
    {
        avl_tree_unlock(source->client_tree);
        return result;
    }

    avl_tree_unlock(source->client_tree);
    return NULL;
}
Пример #18
0
/* rescan the mount list, so that xsl files are updated to show
 * unconnected but active fallback mountpoints
 */
void source_recheck_mounts (int update_all)
{
    ice_config_t *config;
    mount_proxy *mount;

    avl_tree_rlock (global.source_tree);
    config = config_get_config();
    mount = config->mounts;

    if (update_all)
        stats_clear_virtual_mounts ();

    while (mount)
    {
        source_t *source = source_find_mount (mount->mountname);

        if (source)
        {
            source = source_find_mount_raw (mount->mountname);
            if (source)
            {
                mount_proxy *mountinfo = config_find_mount (config, source->mount);
                source_update_settings (config, source, mountinfo);
            }
            else if (update_all)
            {
                stats_event_hidden (mount->mountname, NULL, mount->hidden);
                stats_event_args (mount->mountname, "listenurl", "http://%s:%d%s",
                        config->hostname, config->port, mount->mountname);
                stats_event (mount->mountname, "listeners", "0");
                if (mount->max_listeners < 0)
                    stats_event (mount->mountname, "max_listeners", "unlimited");
                else
                    stats_event_args (mount->mountname, "max_listeners", "%d", mount->max_listeners);
            }
        }
        else
            stats_event (mount->mountname, NULL, NULL);

        /* check for fallback to file */
        if (global.running == ICE_RUNNING && mount->fallback_mount)
        {
            source_t *fallback = source_find_mount (mount->fallback_mount);
            if (fallback == NULL)
            {
                thread_create ("Fallback file thread", source_fallback_file,
                        strdup (mount->fallback_mount), THREAD_DETACHED);
            }
        }

        mount = mount->next;
    }
    avl_tree_unlock (global.source_tree);
    config_release_config();
}
Пример #19
0
/* Check whether this client is currently on this mount, the client may be
 * on either the active or pending lists.
 * return 1 if ok to add or 0 to prevent
 */
static int check_duplicate_logins (source_t *source, client_t *client, auth_t *auth)
{
    /* allow multiple authenticated relays */
    if (client->username == NULL)
        return 1;

    if (auth && auth->allow_duplicate_users == 0)
    {
        avl_node *node;

        avl_tree_rlock (source->client_tree);
        node = avl_get_first (source->client_tree);
        while (node)
        {   
            client_t *existing_client = (client_t *)node->key;
            if (existing_client->username && 
                    strcmp (existing_client->username, client->username) == 0)
            {
                avl_tree_unlock (source->client_tree);
                return 0;
            }
            node = avl_get_next (node);
        }       
        avl_tree_unlock (source->client_tree);

        avl_tree_rlock (source->pending_tree);
        node = avl_get_first (source->pending_tree);
        while (node)
        {
            client_t *existing_client = (client_t *)node->key;
            if (existing_client->username && 
                    strcmp (existing_client->username, client->username) == 0)
            {
                avl_tree_unlock (source->pending_tree);
                return 0;
            }
            node = avl_get_next (node);
        }
        avl_tree_unlock (source->pending_tree);
    }
    return 1;
}
Пример #20
0
/* Check for changes in the YP servers configured */
static void check_servers (void)
{
    struct yp_server *server = (struct yp_server *)active_yps,
                     **server_p = (struct yp_server **)&active_yps;

    while (server)
    {
        if (server->remove)
        {
            struct yp_server *to_go = server;
            DEBUG1 ("YP server \"%s\"removed", server->url);
            *server_p = server->next;
            server = server->next;
            destroy_yp_server (to_go);
            continue;
        }
        server_p = &server->next;
        server = server->next;
    }
    /* add new server entries */
    while (pending_yps)
    {
        avl_node *node;

        server = (struct yp_server *)pending_yps;
        pending_yps = server->next;

        DEBUG1("Add pending yps %s", server->url);
        server->next = (struct yp_server *)active_yps;
        active_yps = server;

        /* new YP server configured, need to populate with existing sources */
        avl_tree_rlock (global.source_tree);
        node = avl_get_first (global.source_tree);
        while (node)
        {
            ypdata_t *yp;

            source_t *source = node->key;
            thread_rwlock_rlock (&source->lock);
            if (source->yp_public && (yp = create_yp_entry (source->mount)) != NULL)
            {
                DEBUG1 ("Adding existing mount %s", source->mount);
                yp->server = server;
                yp->touch_interval = server->touch_interval;
                yp->next = server->mounts;
                server->mounts = yp;
            }
            thread_rwlock_unlock (&source->lock);
            node = avl_get_next (node);
        }
        avl_tree_unlock (global.source_tree);
    }
}
Пример #21
0
static int _free_source_stats(void *key)
{
    stats_source_t *node = (stats_source_t *)key;
    stats_listener_send (node->flags, "DELETE %s\n", node->source);
    DEBUG1 ("delete source node %s", node->source);
    avl_tree_unlock (node->stats_tree);
    avl_tree_free(node->stats_tree, _free_stats);
    free(node->source);
    free(node);

    return 1;
}
Пример #22
0
static void command_show_listeners(client_t *client, source_t *source,
    int response)
{
    xmlDocPtr doc;
    xmlNodePtr node, srcnode, listenernode;
    avl_node *client_node;
    client_t *current;
    char buf[22];
    char *userAgent = NULL;
    time_t now = time(NULL);

    doc = xmlNewDoc("1.0");
    node = xmlNewDocNode(doc, NULL, "icestats", NULL);
    srcnode = xmlNewChild(node, NULL, "source", NULL);
    xmlSetProp(srcnode, "mount", source->mount);
    xmlDocSetRootElement(doc, node);

    memset(buf, '\000', sizeof(buf));
    snprintf(buf, sizeof(buf)-1, "%ld", source->listeners);
    xmlNewChild(srcnode, NULL, "Listeners", buf);

    avl_tree_rlock(source->client_tree);

    client_node = avl_get_first(source->client_tree);
    while(client_node) {
        current = (client_t *)client_node->key;
        listenernode = xmlNewChild(srcnode, NULL, "listener", NULL);
        xmlNewChild(listenernode, NULL, "IP", current->con->ip);
        userAgent = httpp_getvar(current->parser, "user-agent");
        if (userAgent) {
            xmlNewChild(listenernode, NULL, "UserAgent", userAgent);
        }
        else {
            xmlNewChild(listenernode, NULL, "UserAgent", "Unknown");
        }
        memset(buf, '\000', sizeof(buf));
        snprintf(buf, sizeof(buf)-1, "%ld", now - current->con->con_time);
        xmlNewChild(listenernode, NULL, "Connected", buf);
        memset(buf, '\000', sizeof(buf));
        snprintf(buf, sizeof(buf)-1, "%lu", current->con->id);
        xmlNewChild(listenernode, NULL, "ID", buf);
        if (current->username) {
            xmlNewChild(listenernode, NULL, "username", current->username);
        }
        client_node = avl_get_next(client_node);
    }

    avl_tree_unlock(source->client_tree);
    admin_send_response(doc, client, response, 
        LISTCLIENTS_TRANSFORMED_REQUEST);
    xmlFreeDoc(doc);
    client_destroy(client);
}
Пример #23
0
static int command_show_image (client_t *client, const char *mount)
{
    source_t *source;

    avl_tree_rlock (global.source_tree);
    source = source_find_mount_raw (mount);
    if (source && source->format && source->format->get_image)
    {
        thread_mutex_lock (&source->lock);
        avl_tree_unlock (global.source_tree);
        if (source->format->get_image (client, source->format) == 0)
        {
            thread_mutex_unlock (&source->lock);
            return fserve_setup_client (client);
        }
        thread_mutex_unlock (&source->lock);
    }
    else
        avl_tree_unlock (global.source_tree);
    return client_send_404 (client, "No image available");
}
Пример #24
0
xmlDocPtr stats_get_xml (int flags, const char *show_mount)
{
    xmlDocPtr doc;
    xmlNodePtr node;

    doc = xmlNewDoc (XMLSTR("1.0"));
    node = xmlNewDocNode (doc, NULL, XMLSTR("icestats"), NULL);
    xmlDocSetRootElement(doc, node);

    node = _dump_stats_to_doc (node, show_mount, flags);

    if (show_mount && node)
    {
		source_t *source;
        /* show each listener */
        avl_tree_rlock (global.source_tree);
        source = source_find_mount_raw (show_mount);

        if (source)
        {
            thread_mutex_lock (&source->lock);
            admin_source_listeners (source, node);
            thread_mutex_unlock (&source->lock);
            avl_tree_unlock (global.source_tree);
        }
        else
        {
            fbinfo finfo;

            avl_tree_unlock (global.source_tree);
            finfo.flags = FS_FALLBACK;
            finfo.mount = (char*)show_mount;
            finfo.limit = 0;
            finfo.fallback = NULL;

            fserve_list_clients_xml (node, &finfo);
        }
    }
    return doc;
}
Пример #25
0
static void process_source_event (stats_event_t *event)
{
    stats_source_t *snode;

    avl_tree_wlock (_stats.source_tree);
    snode = _find_source(_stats.source_tree, event->source);
    if (snode == NULL)
    {
        if (event->action == STATS_EVENT_REMOVE)
        {
            avl_tree_unlock (_stats.source_tree);
            return;
        }
        snode = (stats_source_t *)calloc(1,sizeof(stats_source_t));
        if (snode == NULL)
            abort();
        DEBUG1 ("new source stat %s", event->source);
        snode->source = (char *)strdup(event->source);
        snode->stats_tree = avl_tree_new(_compare_stats, NULL);
        snode->flags = STATS_SLAVE|STATS_GENERAL|STATS_HIDDEN;

        avl_insert(_stats.source_tree, (void *)snode);
    }
    if (event->action == STATS_EVENT_REMOVE && event->name == NULL)
    {
        int fallback_stream = 0;
        avl_tree_wlock (snode->stats_tree);
        fallback_stream = _find_node (snode->stats_tree, "fallback") == NULL ? 1 : 0;
        if (fallback_stream)
            avl_delete(_stats.source_tree, (void *)snode, _free_source_stats);
        else
            avl_tree_unlock (snode->stats_tree);
        avl_tree_unlock (_stats.source_tree);
        return;
    }
    avl_tree_wlock (snode->stats_tree);
    avl_tree_unlock (_stats.source_tree);
    process_source_stat (snode, event);
    avl_tree_unlock (snode->stats_tree);
}
Пример #26
0
static void process_global_event (stats_event_t *event)
{
    stats_node_t *node = NULL;

    avl_tree_wlock (_stats.global_tree);
    /* DEBUG3("global event %s %s %d", event->name, event->value, event->action); */
    if (event->action == STATS_EVENT_REMOVE)
    {
        /* we're deleting */
        node = _find_node(_stats.global_tree, event->name);
        if (node != NULL)
        {
            stats_listener_send (node->flags, "DELETE global %s\n", event->name);
            avl_delete(_stats.global_tree, (void *)node, _free_stats);
        }
        avl_tree_unlock (_stats.global_tree);
        return;
    }
    node = _find_node(_stats.global_tree, event->name);
    if (node)
    {
        modify_node_event (node, event);
        if ((node->flags & STATS_REGULAR) == 0)
            stats_listener_send (node->flags, "EVENT global %s %s\n", node->name, node->value);
    }
    else
    {
        /* add node */
        node = (stats_node_t *)calloc(1, sizeof(stats_node_t));
        node->name = (char *)strdup(event->name);
        node->value = (char *)strdup(event->value);
        node->flags = event->flags;

        avl_insert(_stats.global_tree, (void *)node);
        stats_listener_send (node->flags, "EVENT global %s %s\n", event->name, event->value);
    }
    avl_tree_unlock (_stats.global_tree);
}
Пример #27
0
void my_free (void *freeblock)
{
    allocheader *block;
    alloc_node *info;
    if (freeblock == NULL)
        return;
    block = (allocheader*)freeblock -1;
    info = block->info;
    avl_tree_wlock (global.alloc_tree);
    info->count--;
    info->allocated -= block->len;
    avl_tree_unlock (global.alloc_tree);
    free (block);
}
Пример #28
0
/* 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
 */
static int add_listener_to_source (source_t *source, client_t *client)
{
    int loop = 10;
    do
    {
        ICECAST_LOG_DEBUG("max on %s is %ld (cur %lu)", source->mount,
                source->max_listeners, source->listeners);
        if (source->max_listeners == -1)
            break;
        if (source->listeners < (unsigned long)source->max_listeners)
            break;

        if (loop && source->fallback_when_full && source->fallback_mount)
        {
            source_t *next = source_find_mount (source->fallback_mount);
            if (!next) {
                ICECAST_LOG_ERROR("Fallback '%s' for full source '%s' not found", 
                        source->mount, source->fallback_mount);
                return -1;
            }

            ICECAST_LOG_INFO("stream full trying %s", next->mount);
            source = next;
            loop--;
            continue;
        }
        /* now we fail the client */
        return -1;

    } while (1);

    client->write_to_client = format_generic_write_to_client;
    client->check_buffer = format_check_http_buffer;
    client->refbuf->len = PER_CLIENT_REFBUF_SIZE;
    memset (client->refbuf->data, 0, PER_CLIENT_REFBUF_SIZE);

    /* lets add the client to the active list */
    avl_tree_wlock (source->pending_tree);
    avl_insert (source->pending_tree, client);
    avl_tree_unlock (source->pending_tree);

    if (source->running == 0 && source->on_demand)
    {
        /* enable on-demand relay to start, wake up the slave thread */
        ICECAST_LOG_DEBUG("kicking off on-demand relay");
        source->on_demand_req = 1;
    }
    ICECAST_LOG_DEBUG("Added client to %s", source->mount);
    return 0;
}
Пример #29
0
int auth_is_listener_connected(source_t *source, char *username)
{
    client_t *client;
    avl_node *client_node;

    avl_tree_rlock(source->client_tree);

    client_node = avl_get_first(source->client_tree);
    while(client_node) {
        client = (client_t *)client_node->key;
        if (client->username) {
            if (!strcmp(client->username, username)) {
                avl_tree_unlock(source->client_tree);
                return 1;
            }
        }
        client_node = avl_get_next(client_node);
    }

    avl_tree_unlock(source->client_tree);
    return 0;

}
Пример #30
0
/* Remove the provided source from the global tree and free it */
void source_free_source (source_t *source)
{
    DEBUG1 ("freeing source \"%s\"", source->mount);
    avl_tree_wlock (global.source_tree);
    avl_delete (global.source_tree, source, NULL);
    avl_tree_unlock (global.source_tree);

    avl_tree_free(source->pending_tree, _free_client);
    avl_tree_free(source->client_tree, _free_client);

    free (source->mount);
    free (source);

    return;
}